基本上,您需要编写一个ITypeMap
和IMemberMap
实现,它可以在内部基于您选择的任何规则(命名约定,如删除S
等标识符、下划线等;属性;或您的情况下的自定义映射)。
这是一个完整的可运行示例,可能会有所帮助:
using Dapper;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;
class SomeType
{
public string Bar { get; set; }
public int Foo { get; set; }
}
static class Program
{
static Program()
{
// only need to do this ONCE
var oldMap = SqlMapper.GetTypeMap(typeof(SomeType));
var map = new CustomTypeMap(typeof(SomeType), oldMap);
map.Map("IFoo", "Foo");
map.Map("SBar", "Bar");
SqlMapper.SetTypeMap(map.Type, map);
}
static void Main()
{
using (var conn = new SqlConnection("Server=.;Database=master;Trusted_Connection=true"))
{
conn.Open();
var row = conn.Query<SomeType>("select 123 as [IFoo], 'abc' as [SBar]").Single();
Console.WriteLine(row.Foo);
Console.WriteLine(row.Bar);
}
}
class CustomTypeMap : SqlMapper.ITypeMap
{
private readonly Dictionary<string, SqlMapper.IMemberMap> members
= new Dictionary<string, SqlMapper.IMemberMap>(StringComparer.OrdinalIgnoreCase);
public Type Type { get { return type; } }
private readonly Type type;
private readonly SqlMapper.ITypeMap tail;
public void Map(string columnName, string memberName)
{
members[columnName] = new MemberMap(type.GetMember(memberName).Single(), columnName);
}
public CustomTypeMap(Type type, SqlMapper.ITypeMap tail)
{
this.type = type;
this.tail = tail;
}
public System.Reflection.ConstructorInfo FindConstructor(string[] names, Type[] types)
{
return tail.FindConstructor(names, types);
}
public SqlMapper.IMemberMap GetConstructorParameter(
System.Reflection.ConstructorInfo constructor, string columnName)
{
return tail.GetConstructorParameter(constructor, columnName);
}
public SqlMapper.IMemberMap GetMember(string columnName)
{
SqlMapper.IMemberMap map;
if (!members.TryGetValue(columnName, out map))
{ // you might want to return null if you prefer not to fallback to the
// default implementation
map = tail.GetMember(columnName);
}
return map;
}
}
class MemberMap : SqlMapper.IMemberMap
{
private readonly MemberInfo member;
private readonly string columnName;
public MemberMap(MemberInfo member, string columnName)
{
this.member = member;
this.columnName = columnName;
}
public string ColumnName { get { return columnName; } }
public System.Reflection.FieldInfo Field { get { return member as FieldInfo; } }
public Type MemberType { get {
switch (member.MemberType)
{
case MemberTypes.Field: return ((FieldInfo)member).FieldType;
case MemberTypes.Property: return ((PropertyInfo)member).PropertyType;
default: throw new NotSupportedException();
}
} }
public System.Reflection.ParameterInfo Parameter { get { return null; } }
public System.Reflection.PropertyInfo Property { get { return member as PropertyInfo; } }
}
}