使用AutoMapper将成员映射委托给子对象

时间:2018-06-21 09:14:18

标签: c# automapper

我有一个目标类,它结合了源类的属性和该源类的内部类。

class Source {
  public int Id {get;set;}
  public int UseThisInt {get;set;}
  public InnerType Inner {get;set;}
  // other properties that the Destination class is not interested in
}
class InnerType {
  public int Id {get;set;}
  public int Height {get;set;}
  // more inner properties
}

我的目标类别应结合UseThisIntInnerType的所有属性。

class Destination {
  public int Id {get;set;}
  public int UseThisInt {get;set;}
  public int Height {get;set;}
  // more inner properties that should map to InnerType
}

现在,我的AutoMapper配置如下:

CreatMap<Source, Destination>()
  .ForMember(d => d.Id, o => o.MapFrom(s => s.Inner.Id))
  .ForMember(d => d.Height, o => o.MapFrom(s => s.Inner.Height));

AutoMapper将在UseThisIntSource之间正确映射Destination,但是我希望能够映射Height这样的Destination中的所有其他属性,而无需明确的ForMember配置。

我尝试使用

Mapper.Initialize(cfg => cfg.CreateMap<Source, Destination>()
  .ForMember(d => d.Id, o => o.MapFrom(s => s.Inner.Id))
  .ForMember(d => d.UseThisInt, o => o.MapFrom(s => s.UseThisInt))
  .ForAllOtherMembers(o => o.MapFrom(source=> source.Inner))
);

,但是没有达到预期的效果,并且保持Destination.Height不变。

2 个答案:

答案 0 :(得分:4)

AutoMapper的大多数示例演示了如何从某些源对象创建新的Destination对象,但是AutoMapper也可以用于 更新 从源对象获取这些属性的现有对象映射,并且保留所有剩余属性。

因此,可以分多个步骤从源映射到目标。


因此,如果您像这样从InnerType创建映射配置:-

Mapper.Initialize(cfg => {
    cfg.CreateMap<Source, Destination>();
    cfg.CreateMap<InnerType, Destination>();
});

然后,您可以利用此功能通过两次映射到目标对象来覆盖映射。

var dest = Mapper.Map<Destination>(src);
Mapper.Map(src.Inner, dest);

此方法的一个缺点是,在使用Mapper生成Destination对象时,您需要注意这一点。但是,您可以选择在AfterMap指令中声明AutoMapper配置中的第二个映射步骤。

Mapper.Initialize(cfg => {
        cfg.CreateMap<Source, Destination>()
            .AfterMap((src, dest) => Mapper.Map(src.Inner, dest));
        cfg.CreateMap<InnerType, Destination>();
    });

使用此更新的配置,您可以通过一个Map调用执行映射:-

var dest = Mapper.Map<Destination>(src);

答案 1 :(得分:0)

CreateMap<Source, Destination>()
        .AfterMap((src, dest) =>
        {
          dest.Height = src.Inner.Height;
        });