Skip to content

Instantly share code, notes, and snippets.

@jtabuloc
Last active June 11, 2018 04:55
Show Gist options
  • Save jtabuloc/8ea5cd74680ab43de6cf096d521c1fd7 to your computer and use it in GitHub Desktop.
Save jtabuloc/8ea5cd74680ab43de6cf096d521c1fd7 to your computer and use it in GitHub Desktop.
This custom column attribute mapper will serve only as personal copy and an example.
using Dapper;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace ColumnAttrMapper
{
public class BaseTypeMapper : SqlMapper.ITypeMap
{
private readonly IEnumerable<SqlMapper.ITypeMap> _mappers;
public BaseTypeMapper(IEnumerable<SqlMapper.ITypeMap> mappers)
{
_mappers = mappers;
}
public ConstructorInfo FindConstructor(string[] names, Type[] types)
{
foreach (var mapper in _mappers)
{
try
{
ConstructorInfo result = mapper.FindConstructor(names, types);
if (result != null) return result;
}
catch (NotImplementedException)
{
}
}
return null;
}
public ConstructorInfo FindExplicitConstructor()
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.FindExplicitConstructor();
if (result != null) return result;
}
catch (NotImplementedException)
{
}
}
return null;
}
public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetConstructorParameter(constructor, columnName);
if (result != null) return result;
}
catch (NotImplementedException)
{
}
}
return null;
}
public SqlMapper.IMemberMap GetMember(string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetMember(columnName);
if (result != null) return result;
}
catch (NotImplementedException)
{
}
}
return null;
}
}
}
using Dapper;
using System;
using System.Linq;
using System.Reflection;
namespace ColumnAttrMapper
{
/// <summary>
/// Use this column Mapper to register your entities with column annotation. This columnMapper use Dapper 1.50.5 version.
/// </summary>
public static class ColumnMapper
{
/// <summary>
/// Pass the namespace of your entity that has column attribute annotation
/// </summary>
/// <param name="namespace"></param>
public static void Register(string @namespace)
{
var types = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(type => type.IsClass && type.Namespace == @namespace)
.ToList();
types.ForEach(type =>
{
var typeMapper = Activator.CreateInstance(typeof(TypeMapper<>).MakeGenericType(type));
SqlMapper.SetTypeMap(type, (SqlMapper.ITypeMap)typeMapper);
});
}
}
}
using Dapper;
using System;
using System.Linq;
using System.Reflection;
namespace ColumnAttrMapper
{
public sealed class TypeMapper<T> : BaseTypeMapper
{
public TypeMapper() : base(new SqlMapper.ITypeMap[]
{
new CustomPropertyTypeMap(typeof (T), SelectProperty),
new DefaultTypeMap(typeof (T))
})
{
}
private static PropertyInfo SelectProperty(Type type, string columnName)
{
return type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.FirstOrDefault(property => HasColumnAttribute(property, columnName) &&
IsReadyOnlyProperty(property, type));
}
private static bool HasColumnAttribute(PropertyInfo property, string columnName)
{
return property.GetCustomAttributes(false)
.Any(attr => attr.GetType().Name == "ColumnAttribute" &&
attr.GetType()
.GetProperties(BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance)
.Any(f => f.Name == "Name" &&
string.Compare(f.GetValue(attr).ToString(), columnName, true) == 0));
}
private static bool IsReadyOnlyProperty(PropertyInfo property, Type type)
{
return (property.DeclaringType == type
? property.GetSetMethod(true)
: property.DeclaringType
.GetProperty(property.Name,
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance)
.GetSetMethod(true)) != null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment