我正在处理的应用程序有几个地方我们使用AutoMapper来映射实体。
问题是,如果我从项目的一侧到另一侧有一个模型实体,很多时候我忘记为新实体添加映射(我只需要从其他实体复制粘贴),最后得到解决方案编译,我也不例外。
它只是在没有完整功能且没有调试消息的情况下启动应用程序,这很难弄清楚我错过了什么。
有没有办法在编译时强制编译器给我一个错误,以防我忘记进行映射?
答案 0 :(得分:1)
AFAIK,没有可能强制对Automapper进行编译时检查。 不过,有可能验证映射的正确性: 在您定义了所有映射之后,调用 AssertConfigurationIsValid 方法,如果定义的映射被破坏,将抛出 AutoMapperConfigurationException 异常。
您可以将其作为单元或集成测试套件的一部分。
答案 1 :(得分:0)
我遇到了同样的问题,并决定通过包装AutoMapper来解决它。对于每个源 - 目标地图,我提供了一种方法,我在将其添加到AutoMapper配置文件后创建。
这可能会带走一些实现AutoMapper的难易程度,但我发现编译时检查值得。
public class MyType {
public string SomeProperty { get;set; }
}
public class MyOtherType {
public string SomeProperty { get;set; }
}
public class MyAlternateType {
public string AlternateProperty {get;set;}
}
public class AutoMapperProfile : Profile {
public AutoMapperProfile() {
CreateMap<MyType, MyOtherType>();
CreateMap<MyAlternateType, MyOtherType>()
.ForMember(ot => ot.SomeProperty, options => options.MapFrom(at => at.AlternateProperty));
}
}
public interface IMyMappingProvider {
// Uncomment below for Queryable Extensions
//IQueryable<TDestination> ProjectTo<TSource, TDestination>(IQueryable<TSource> source, params Expression<Func<TDestination, object>>[] membersToExpand);
//IQueryable<TDestination> ProjectTo<TSource, TDestination>(IQueryable<TSource> source, IDictionary<string, object> parameters, params string[] membersToExpand);
/*
* Add your mapping declarations below
*/
MyOtherType MapToMyOtherType(MyType source);
MyOtherType MapToMyOtherType(MyAlternateType source);
}
public class MyMappingProvider : IMyMappingProvider {
private IMapper Mapper { get; set; }
public MyMappingProvider(IMapper mapper) {
Mapper = mapper;
}
/* Uncomment this for Queryable Extensions
public IQueryable<TDestination> ProjectTo<TSource, TDestination>(IQueryable<TSource> source, params Expression<Func<TDestination, object>>[] membersToExpand) {
return new ProjectionExpression(source, Mapper.ConfigurationProvider.ExpressionBuilder).To<TDestination>(null, membersToExpand);
}
public IQueryable<TDestination> ProjectTo<TSource, TDestination>(IQueryable<TSource> source, IDictionary<string, object> parameters, params string[] membersToExpand) {
return new ProjectionExpression(source, Mapper.ConfigurationProvider.ExpressionBuilder).To<TDestination>(parameters, membersToExpand);
}
*/
/*
* Implement your mapping methods below
*/
public MyOtherType MapToMyOtherType(MyType source) {
return Mapper.Map<MyType, MyOtherType>(source);
}
public MyOtherType MapToMyOtherType(MyAlternateType source) {
return Mapper.Map<MyAlternateType, MyOtherType>(source);
}
}
如果您使用的是AutoMapper的可查询扩展程序,则可以添加以下类并取消注释上面的可查询扩展代码。
public static class QueryableExtensions {
/*
* Implement your extension methods below
*/
public static IQueryable<MyOtherType> ProjectToMyOtherType(this IQueryable<MyType> source, IMyMappingProvider mapper, params Expression<Func<MyOtherType, object>>[] membersToExpand)
{
return mapper.ProjectTo<MyType, MyOtherType>(source, membersToExpand);
}
public static IQueryable<MyOtherType> ProjectToMyOtherType(this IQueryable<MyAlternateType> source, IMyMappingProvider mapper, params Expression<Func<MyOtherType, object>>[] membersToExpand)
{
return mapper.ProjectTo<MyAlternateType, MyOtherType>(source, membersToExpand);
}
}
使用LinqPad使用AutoMapper 6.1.1进行测试:
var autoMapperConfig = new MapperConfiguration(cfg => { cfg.AddProfile(new AutoMapperProfile()); });
IMyMappingProvider mapper = new MyMappingProvider(autoMapperConfig.CreateMapper());
var myTypes = new List<MyType>()
{
new MyType() {SomeProperty = "Test1"},
new MyType() {SomeProperty = "Test2"},
new MyType() {SomeProperty = "Test3"}
};
myTypes.AsQueryable().ProjectToMyOtherType(mapper).Dump();
var myAlternateTypes = new List<MyAlternateType>()
{
new MyAlternateType() {AlternateProperty = "AlternateTest1"},
new MyAlternateType() {AlternateProperty = "AlternateTest2"},
new MyAlternateType() {AlternateProperty = "AlternateTest3"}
};
myAlternateTypes.AsQueryable().ProjectToMyOtherType(mapper).Dump();
mapper.MapToMyOtherType(myTypes[0]).Dump();
正如@ serge.karalenka所说,不要忘记通过调用AssertConfigurationIsValid()来测试你的映射配置。