delegating Member mapping to child object with Aut

2019-08-03 04:27发布

问题:

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.

回答1:

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


标签: c# AutoMapper