我已经开始研究AutoMapper并且有一个'数据驱动'场景......我有基于我传递的一些'架构信息'从SqlDataReader填充实体属性的代码......
接下来我想获取实体属性...然后根据我的Schema信息,从实体值创建一组SqlParameters ...
AutoMapper的完美工作......但是我看到很多从对象图到对象图的扁平化但是这个任务没有简单的样本......当我去做它时,我偶然发现了一些细微差别但是粗略地了解我应该做些什么...
我已经起草了以下内容......我正在尝试使用TypeConverters并提前注册它们,但是当我执行实际的map.ForMember()操作时会抛出错误抱怨
“仅对某个类型的顶级个人成员支持成员的自定义配置。”
我尝试过的一些变化并没有成功...
(1)尝试了更简单的版本...... (2)尝试使用ConstructUsing()机制然后操作的目标实际上是SqlParameter。[[[Value]]]属性(很可能是AutoMapper心态中的'正确'方式对吗?) (3)尝试预先建立目标列表然后“找到”匹配参数 - 但是设置.Value仍然是该等式中缺失的一部分......
成为AutoMapper的新手我预计会遇到一些挑战,但我已经花了足够的时间在这上面并没有找到任何明显的东西......看起来它应该是框架的一个简单用例......我一定是缺少一些东西明显...
class Program
{
static void Main(string[] args)
{
// Drive it by some data... Say some mapping info we have from elsewhere...
var myMappingPairs = new List<MyMappingInfo>()
{
new MyMappingInfo() { PropertyName = "MyGuidProperty", ParameterName = "Param00" },
new MyMappingInfo() { PropertyName = "MyStringProperty", ParameterName = "Param01" },
new MyMappingInfo() { PropertyName = "MyInt16Property", ParameterName = "Param02" },
new MyMappingInfo() { PropertyName = "MyInt32Property", ParameterName = "Param03" },
new MyMappingInfo() { PropertyName = "MyInt64Property", ParameterName = "Param04" }
};
// We can try to register these, but the sytax isn't clear to me yet...
Mapper.CreateMap<Guid, SqlParameter>().ConvertUsing<GuidToSqlParameterConverter>();
Mapper.CreateMap<String, SqlParameter>().ConvertUsing<StringToSqlParameterConverter>();
Mapper.CreateMap<Int16, SqlParameter>().ConvertUsing<Int16ToSqlParameterConverter>();
Mapper.CreateMap<Int32, SqlParameter>().ConvertUsing<Int32ToSqlParameterConverter>();
Mapper.CreateMap<Int64, SqlParameter>().ConvertUsing<Int64ToSqlParameterConverter>();
// Next we'll build our mapping from the "pairings"...
var map = Mapper.CreateMap<MySourceEntity, List<SqlParameter>>();
foreach (var mappingPair in myMappingPairs)
{
map.ForMember
(
destination => destination,
options => options.ResolveUsing<PropertyNameResolver>().FromMember
(
mappingPair.PropertyName // <-- Data Driven Property Name...
)
);
}
// Create a test entity...
var entity = new MySourceEntity()
{
MyGuidProperty = Guid.NewGuid(),
MyStringProperty = "Hello AutoMapper",
MyInt16Property = Int16.MaxValue,
MyInt32Property = Int32.MaxValue,
MyInt64Property = Int64.MaxValue
};
// Map it...
var values = Mapper.Map<MySourceEntity, object[]>
(
entity
);
}
}
public class MySourceEntity
{
public string MyStringProperty { get; set; }
public DateTime? MyDateTimeProperty { get; set; }
public Byte? MyByteProperty { get; set; }
public Int16? MyInt16Property { get; set; }
public Int32? MyInt32Property { get; set; }
public Int64? MyInt64Property { get; set; }
public Guid? MyGuidProperty { get; set; }
public List<String> ThisShouldntGetMapped { get; set; }
public StringBuilder NorShouldThis { get; set; }
}
public class MyMappingInfo
{
public String PropertyName { get; set; }
public String ParameterName { get; set; }
public SqlDbType SqlDbType { get; set; }
}
public class GuidToSqlParameterConverter : AutoMapper.ITypeConverter<Guid, SqlParameter>
{
public SqlParameter Convert(ResolutionContext context)
{
if (context.IsSourceValueNull)
{
return new SqlParameter()
{
ParameterName = "GuidParam",
SqlDbType = SqlDbType.UniqueIdentifier,
Value = DBNull.Value
};
}
else
{
return new SqlParameter()
{
ParameterName = "GuidParam",
SqlDbType = SqlDbType.UniqueIdentifier,
Value = context.SourceValue
};
}
}
}
public class StringToSqlParameterConverter : AutoMapper.ITypeConverter<string, SqlParameter>
{
public SqlParameter Convert(ResolutionContext context)
{
if (context.IsSourceValueNull)
{
return new SqlParameter()
{
ParameterName = "StringParam",
SqlDbType = SqlDbType.NVarChar,
Value = DBNull.Value
};
}
else
{
return new SqlParameter()
{
ParameterName = "StringParam",
SqlDbType = SqlDbType.NVarChar,
Value = context.SourceValue
};
}
}
}
public class Int16ToSqlParameterConverter : AutoMapper.ITypeConverter<Int16, SqlParameter>
{
public SqlParameter Convert(ResolutionContext context)
{
if (context.IsSourceValueNull)
{
return new SqlParameter()
{
ParameterName = "Int16Param",
SqlDbType = SqlDbType.SmallInt,
Value = DBNull.Value
};
}
else
{
return new SqlParameter()
{
ParameterName = "Int16Param",
SqlDbType = SqlDbType.SmallInt,
Value = context.SourceValue
};
}
}
}
public class Int32ToSqlParameterConverter : AutoMapper.ITypeConverter<Int32, SqlParameter>
{
public SqlParameter Convert(ResolutionContext context)
{
if (context.IsSourceValueNull)
{
return new SqlParameter()
{
ParameterName = "Int32Param",
SqlDbType = SqlDbType.Int,
Value = DBNull.Value
};
}
else
{
return new SqlParameter()
{
ParameterName = "Int32Param",
SqlDbType = SqlDbType.Int,
Value = context.SourceValue
};
}
}
}
public class Int64ToSqlParameterConverter : AutoMapper.ITypeConverter<Int64, SqlParameter>
{
public SqlParameter Convert(ResolutionContext context)
{
if (context.IsSourceValueNull)
{
return new SqlParameter()
{
ParameterName = "Int64Param",
SqlDbType = SqlDbType.BigInt,
Value = DBNull.Value
};
}
else
{
return new SqlParameter()
{
ParameterName = "Int64Param",
SqlDbType = SqlDbType.BigInt,
Value = context.SourceValue
};
}
}
}
}
我想知道AutoMapper中生成的运行时代码是否比表示更好:
static IDictionary<string, object> GetDictionaryFromObject(object obj)
{
if (obj == null) return new Dictionary<string, object>();
return obj.GetType().GetProperties()
.ToDictionary(p => p.Name,
p => p.GetValue(obj, null) ?? DBNull.Value);
}
对我来说使用AutoMapper的全部意义......我已经知道如何编写反射代码......我总是可以看一下基于纯反射的库来获得额外的性能提升,但我认为AutoMapper可能会是两只鸟 - 一石头......