diff --git a/Dapper/PublicAPI.Unshipped.txt b/Dapper/PublicAPI.Unshipped.txt index 91b0e1a43..6fd5aa3bc 100644 --- a/Dapper/PublicAPI.Unshipped.txt +++ b/Dapper/PublicAPI.Unshipped.txt @@ -1 +1,2 @@ -#nullable enable \ No newline at end of file +#nullable enable +static Dapper.SqlMapper.AddTypeHandlerImpl(System.Type! type, Dapper.SqlMapper.ITypeHandler? handler) -> void \ No newline at end of file diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 47e40ea41..ebcf7f675 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -255,22 +255,19 @@ static SqlMapper() [typeof(TimeOnly?)] = TypeMapEntry.DoNotSetFieldValue, #endif }; - ResetTypeHandlers(false); + ResetTypeHandlers(); } /// /// Clear the registered type handlers. /// - public static void ResetTypeHandlers() => ResetTypeHandlers(true); - [MemberNotNull(nameof(typeHandlers))] - private static void ResetTypeHandlers(bool clone) - { + public static void ResetTypeHandlers() { typeHandlers = []; - AddTypeHandlerImpl(typeof(DataTable), new DataTableHandler(), clone); - AddTypeHandlerImpl(typeof(XmlDocument), new XmlDocumentHandler(), clone); - AddTypeHandlerImpl(typeof(XDocument), new XDocumentHandler(), clone); - AddTypeHandlerImpl(typeof(XElement), new XElementHandler(), clone); + AddTypeHandlerImpl(typeof(DataTable), new DataTableHandler()); + AddTypeHandlerImpl(typeof(XmlDocument), new XmlDocumentHandler()); + AddTypeHandlerImpl(typeof(XDocument), new XDocumentHandler()); + AddTypeHandlerImpl(typeof(XElement), new XElementHandler()); } /// @@ -339,7 +336,7 @@ public static void RemoveTypeMap(Type type) /// /// The type to handle. /// The handler to process the . - public static void AddTypeHandler(Type type, ITypeHandler handler) => AddTypeHandlerImpl(type, handler, true); + public static void AddTypeHandler(Type type, ITypeHandler handler) => AddTypeHandlerImpl(type, handler); /// /// Determine if the specified type will be processed by a custom handler. /// @@ -353,7 +350,15 @@ public static void RemoveTypeMap(Type type) /// The type to handle. /// The handler to process the . /// Whether to clone the current type handler map. - public static void AddTypeHandlerImpl(Type type, ITypeHandler? handler, bool clone) + [Obsolete("Please use overload of " + nameof(AddTypeHandlerImpl) + " without the clone parameter. This API may be removed at a later date.")] + public static void AddTypeHandlerImpl(Type type, ITypeHandler? handler, bool clone) => AddTypeHandlerImpl(type, handler); + + /// + /// Configure the specified type to be processed by a custom handler. + /// + /// The type to handle. + /// The handler to process the . + public static void AddTypeHandlerImpl(Type type, ITypeHandler? handler) { if (type is null) throw new ArgumentNullException(nameof(type)); @@ -373,10 +378,21 @@ public static void AddTypeHandlerImpl(Type type, ITypeHandler? handler, bool clo } } - var snapshot = typeHandlers; - if (snapshot.TryGetValue(type, out var oldValue) && handler == oldValue) return; // nothing to do - - var newCopy = clone ? new Dictionary(snapshot) : snapshot; + lock (typeHandlers) + { + if (typeHandlers.TryGetValue(type, out var oldValue) && handler == oldValue) return; // nothing to do + + if (handler is null) + { + typeHandlers.Remove(type); + if (secondary is not null) typeHandlers.Remove(secondary); + } + else + { + typeHandlers[type] = handler; + if (secondary is not null) typeHandlers[secondary] = handler; + } + } #pragma warning disable 618 typeof(TypeHandlerCache<>).MakeGenericType(type).GetMethod(nameof(TypeHandlerCache.SetHandler), BindingFlags.Static | BindingFlags.NonPublic)!.Invoke(null, [handler]); @@ -385,17 +401,6 @@ public static void AddTypeHandlerImpl(Type type, ITypeHandler? handler, bool clo typeof(TypeHandlerCache<>).MakeGenericType(secondary).GetMethod(nameof(TypeHandlerCache.SetHandler), BindingFlags.Static | BindingFlags.NonPublic)!.Invoke(null, [handler]); } #pragma warning restore 618 - if (handler is null) - { - newCopy.Remove(type); - if (secondary is not null) newCopy.Remove(secondary); - } - else - { - newCopy[type] = handler; - if (secondary is not null) newCopy[secondary] = handler; - } - typeHandlers = newCopy; } /// @@ -403,7 +408,7 @@ public static void AddTypeHandlerImpl(Type type, ITypeHandler? handler, bool clo /// /// The type to handle. /// The handler for the type . - public static void AddTypeHandler(TypeHandler handler) => AddTypeHandlerImpl(typeof(T), handler, true); + public static void AddTypeHandler(TypeHandler handler) => AddTypeHandlerImpl(typeof(T), handler); private static Dictionary typeHandlers; @@ -479,7 +484,7 @@ public static void SetDbType(IDataParameter parameter, object value) { handler = (ITypeHandler)Activator.CreateInstance( typeof(SqlDataRecordHandler<>).MakeGenericType(argTypes))!; - AddTypeHandlerImpl(type, handler, true); + AddTypeHandlerImpl(type, handler); return DbType.Object; } catch