忘记使用AutoMapper映射类

时间:2015-03-18 11:52:23

标签: automapper

我正在处理的应用程序有几个地方我们使用AutoMapper来映射实体。

问题是,如果我从项目的一侧到另一侧有一个模型实体,很多时候我忘记为新实体添加映射(我只需要从其他实体复制粘贴),最后得到解决方案编译,我也不例外。

它只是在没有完整功能且没有调试消息的情况下启动应用程序,这很难弄清楚我错过了什么。

有没有办法在编译时强制编译器给我一个错误,以防我忘记进行映射?

2 个答案:

答案 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()来测试你的映射配置。