Dapper unterstützt jetzt benutzerdefinierte Zuordnungen von Spalten zu Eigenschaften. Dies geschieht über die ITypeMap- Schnittstelle. Dapper stellt eine CustomPropertyTypeMap- Klasse bereit, die den größten Teil dieser Arbeit erledigen kann. Beispielsweise:
Dapper.SqlMapper.SetTypeMap(
typeof(TModel),
new CustomPropertyTypeMap(
typeof(TModel),
(type, columnName) =>
type.GetProperties().FirstOrDefault(prop =>
prop.GetCustomAttributes(false)
.OfType<ColumnAttribute>()
.Any(attr => attr.Name == columnName))));
Und das Modell:
public class TModel {
[Column(Name="my_property")]
public int MyProperty { get; set; }
}
Es ist wichtig zu beachten, dass die Implementierung von CustomPropertyTypeMap erfordert, dass das Attribut vorhanden ist und mit einem der Spaltennamen übereinstimmt, da sonst die Eigenschaft nicht zugeordnet wird. Die DefaultTypeMap- Klasse bietet die Standardfunktionalität und kann genutzt werden, um dieses Verhalten zu ändern:
public class FallbackTypeMapper : SqlMapper.ITypeMap
{
private readonly IEnumerable<SqlMapper.ITypeMap> _mappers;
public FallbackTypeMapper(IEnumerable<SqlMapper.ITypeMap> mappers)
{
_mappers = mappers;
}
public SqlMapper.IMemberMap GetMember(string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetMember(columnName);
if (result != null)
{
return result;
}
}
catch (NotImplementedException nix)
{
// the CustomPropertyTypeMap only supports a no-args
// constructor and throws a not implemented exception.
// to work around that, catch and ignore.
}
}
return null;
}
// implement other interface methods similarly
// required sometime after version 1.13 of dapper
public ConstructorInfo FindExplicitConstructor()
{
return _mappers
.Select(mapper => mapper.FindExplicitConstructor())
.FirstOrDefault(result => result != null);
}
}
Auf diese Weise wird es einfach, einen benutzerdefinierten Typ-Mapper zu erstellen, der die Attribute automatisch verwendet, wenn sie vorhanden sind, ansonsten aber auf das Standardverhalten zurückgreift:
public class ColumnAttributeTypeMapper<T> : FallbackTypeMapper
{
public ColumnAttributeTypeMapper()
: base(new SqlMapper.ITypeMap[]
{
new CustomPropertyTypeMap(
typeof(T),
(type, columnName) =>
type.GetProperties().FirstOrDefault(prop =>
prop.GetCustomAttributes(false)
.OfType<ColumnAttribute>()
.Any(attr => attr.Name == columnName)
)
),
new DefaultTypeMap(typeof(T))
})
{
}
}
Das heißt, wir können jetzt problemlos Typen unterstützen, für die eine Zuordnung erforderlich ist, indem wir Attribute verwenden:
Dapper.SqlMapper.SetTypeMap(
typeof(MyModel),
new ColumnAttributeTypeMapper<MyModel>());
Hier ist eine Zusammenfassung des vollständigen Quellcodes .