Automapper:如何消除重复映射?

时间:2017-09-14 19:00:20

标签: c# asp.net entity-framework automapper poco

我有以下表格结构。这两个表有20多个常见属性,我只列出了两个。我也有10张类似的表。这就是表在数据库中的方式。有超过10个具有相似属性的具体表格,并且不以任何方式相互连接。我正在使用POCO生成器从我的数据库生成类。

public class A
 {
    public string name {get;set;}
    public string address {get;set;}
    public string AId {get;set;}
  }

public class B
 {
    public string name {get;set;}
    public string address {get;set;}
    public string BId {get;set;}
  } 

我有以下viewModels:

public class BaseViewModel
 {
    public string Fullname {get;set;}
    public string Fulladdress {get;set;}
   }

public class AviewModel : BaseViewModel
 {
    public string AId {get;set;}
  }

public class BViewModel : BaseViewModel
 {
     public string BId {get;set;}
  } 

当我创建映射时,我必须为我创建的每个viewModel重复所有这些。

config.CreateMap<A, AviewModel>()
.ForMember(dest => Fulladdress, opt => opt.MapFrom(src =>.address))
.ForMember(dest => Fullname, opt => opt.MapFrom(src =>.name)).ReverseMap();


config.CreateMap<B, BviewModel>()
.ForMember(dest => Fulladdress, opt => opt.MapFrom(src =>.address))
.ForMember(dest => Fullname, opt => opt.MapFrom(src =>.name)).ReverseMap();

是否可以减少我可能需要做的重复映射?

3 个答案:

答案 0 :(得分:2)

您需要源类的基类。您在基本源类和目标类之间创建一个映射。您可以在映射中将该映射包含在派生类中。这将允许您重用配置。 The docs。对于简单的情况,您可以使用As而不是Include。

答案 1 :(得分:2)

您可以将公共映射代码移动到辅助程序通用方法。您将TDestination类型约束为派生自BaseViewModel的类,从而允许以ForMember方法访问目标成员。对于源映射,您将使用MapFrom重载接受string属性名称:

public static class CommonMappings
{
    public static IMappingExpression<TSource, TDestination> MapToBaseViewModel<TSource, TDestination>(this IMappingExpression<TSource, TDestination> map)
        where TDestination : BaseViewModel
    {
        return map
            .ForMember(dest => dest.Fulladdress, opt => opt.MapFrom("address"))
            .ForMember(dest => dest.Fullname, opt => opt.MapFrom("name"));
    }
}

然后你可以像这样使用它:

config.CreateMap<A, AViewModel>()
    .MapToBaseViewModel()
    // ... specific mappings
    .ReverseMap();

config.CreateMap<B, BViewModel>()
    .MapToBaseViewModel()
    // ... specific mappings
    .ReverseMap();

更新:事实证明,此时最新的自动反向映射AutoMapper 6.1.1适用于MapFrom的lambda重载,但不适用于string过载(在AutoMapper 5中它根本不起作用)。因此,在修复之前,您可以使用以下MapFrom(string)替换:

public static class AMExtensions
{
    public static void From<TSource, TDestination, TMember>(this IMemberConfigurationExpression<TSource, TDestination, TMember> opt, string name)
    {
        var parameter = Expression.Parameter(typeof(TSource), "src");
        var body = Expression.PropertyOrField(parameter, name);
        var selector = Expression.Lambda(body, parameter);
        opt.MapFrom((dynamic)selector);
    }
}

这意味着您需要使用MapFrom替换原始解决方案中的From次来电,因为我们无法为扩展方法指定相同的名称,因为它的优先级低于具体的界面方法。

与基类方法相比,可能需要付出太多努力。但如果您无法控制实体类的设计,则非常有用。

答案 2 :(得分:0)

您在模型的属性上设置属性。 它包含它在源对象上映射的属性的名称。

然后创建一个接受目标对象和源对象的泛型方法,该方法在设置属性的属性上找到customattribute,在目标对象上找到属性(反之亦然),然后设置值。 / p>

您甚至可以通过询问是否为类属性来处理嵌套对象。