使用AutoMapper将成员映射委托给子对象 [英] delegating Member mapping to child object with AutoMapper

查看:236
本文介绍了使用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可以正确地在SourceDestination之间映射UseThisInt,但是我希望能够在没有显式ForMember配置的情况下使其映射Destination中的所有其他属性,例如Height.

我尝试使用

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不变.

解决方案

AutoMapper的大多数示例演示了如何从某些源对象创建新的Destination对象,但是AutoMapper也可以用于 update :现有对象从源对象获取那些已映射的属性,而其余所有属性保持不变.

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


因此,如果您像这样从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指令.

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);

I have a destination class that combines properties from a source class and an inner class of that source class.

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
}

my destination class should combine UseThisInt and all properties of the InnerType.

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
}

Now my AutoMapper configuration looks like this:

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 will correctly map UseThisInt between Source and Destination, but I would like to be able to let it map all the other properties in Destination like Height without an explicit ForMember configuration.

I tried using

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))
);

, but that did not achieve the intended result and left Destination.Height untouched.

解决方案

Most examples of AutoMapper demonstrate creating a new Destination object from some source object, but AutoMapper can also be used to update an existing object taking those properties from the source object that are mapped and leaving any remaining properties untouched.

Consequently it is possible to map from the source to the destination in multiple steps.


So if you create a mapping configuration from InnerType like so:-

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

Then you can make use of this ability to overlay mappings by mapping into the destination object twice.

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

One downside to this approach is that you need to be mindful of this when using the Mapper to generate a Destination object. However, you have the option of declaring this second mapping step within your AutoMapper configuration as an AfterMap instruction.

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

With this updated configuration you can perform the mapping with a single Map call:-

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

这篇关于使用AutoMapper将成员映射委托给子对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆