Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Dapper users to specify custom default type maps #132

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 21 additions & 8 deletions Dapper NET40/SqlMapper.cs
Expand Up @@ -699,6 +699,8 @@ public static int GetCachedSQLCount()

static SqlMapper()
{
SetDefaultTypeMap(t => new DefaultTypeMap(t));

typeMap = new Dictionary<Type, DbType>();
typeMap[typeof(byte)] = DbType.Byte;
typeMap[typeof(sbyte)] = DbType.SByte;
Expand Down Expand Up @@ -3554,7 +3556,7 @@ static readonly MethodInfo
getItem = typeof(IDataRecord).GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.GetIndexParameters().Any() && p.GetIndexParameters()[0].ParameterType == typeof(int))
.Select(p => p.GetGetMethod()).First();

/// <summary>
/// Gets type-map for the given type
/// </summary>
Expand All @@ -3580,14 +3582,25 @@ public static ITypeMap GetTypeMap(Type type)

if (map == null)
{
map = new DefaultTypeMap(type);
map = _defaultTypeMapFactory(type);
_typeMaps[type] = map;
}
}
}
return map;
}

private static Func<Type, ITypeMap> _defaultTypeMapFactory;

/// <summary>
/// Set a custom mapping for all types
/// </summary>
/// <param name="factory">A function that creates the ITypeMap</param>
public static void SetDefaultTypeMap(Func<Type, ITypeMap> factory)
{
_defaultTypeMapFactory = factory;
}

// use Hashtable to get free lockless reading
#if DNXCORE50
private static readonly Dictionary<Type,ITypeMap> _typeMaps = new Dictionary<Type, ITypeMap>();
Expand All @@ -3604,8 +3617,8 @@ public static void SetTypeMap(Type type, ITypeMap map)
{
if (type == null)
throw new ArgumentNullException("type");

if (map == null || map is DefaultTypeMap)
if (map == null)
{
lock (_typeMaps)
{
Expand Down Expand Up @@ -5335,7 +5348,7 @@ public ParameterInfo Parameter
/// <summary>
/// Represents default type mapping strategy used by Dapper
/// </summary>
sealed partial class DefaultTypeMap : SqlMapper.ITypeMap
partial class DefaultTypeMap : SqlMapper.ITypeMap
{
private readonly List<FieldInfo> _fields;
private readonly List<PropertyInfo> _properties;
Expand Down Expand Up @@ -5404,7 +5417,7 @@ internal static List<FieldInfo> GetSettableFields(Type t)
/// <param name="names">DataReader column names</param>
/// <param name="types">DataReader column types</param>
/// <returns>Matching constructor or default one</returns>
public ConstructorInfo FindConstructor(string[] names, Type[] types)
public virtual ConstructorInfo FindConstructor(string[] names, Type[] types)
{
var constructors = _type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (ConstructorInfo ctor in constructors.OrderBy(c => c.IsPublic ? 0 : (c.IsPrivate ? 2 : 1)).ThenBy(c => c.GetParameters().Length))
Expand Down Expand Up @@ -5466,7 +5479,7 @@ public ConstructorInfo FindExplicitConstructor()
/// <param name="constructor">Constructor to resolve</param>
/// <param name="columnName">DataReader column name</param>
/// <returns>Mapping implementation</returns>
public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
public virtual SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
{
var parameters = constructor.GetParameters();

Expand All @@ -5478,7 +5491,7 @@ public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor,
/// </summary>
/// <param name="columnName">DataReader column name</param>
/// <returns>Mapping implementation</returns>
public SqlMapper.IMemberMap GetMember(string columnName)
public virtual SqlMapper.IMemberMap GetMember(string columnName)
{
var property = _properties.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.Ordinal))
?? _properties.FirstOrDefault(p => string.Equals(p.Name, columnName, StringComparison.OrdinalIgnoreCase));
Expand Down