如何使用AutoMapper将目标对象与源对象中的子对象映射?

我有这样的源和目标对象:

class ProductWithCategories // Source class { public Product Product { get; set; } // Product is an EF entity class public IEnumerable Categories { get; set; } } class ProductViewModel // Dest class { public int Id { get; set; } // Other properties with the same name as Product class public IEnumerable Categories { get; set; } } 

因此,我需要将source.Product的值source.Productdest ,然后将dest.Categoriesdest.Categories 。 AutoMapper有可能吗?

我试过了这个,当它失败时我并不感到惊讶:

  config.CreateMap() .ForMember(q => q, option => option.MapFrom(q => q.Product)) .ForMember(q => q.Categories, option => option.MapFrom(q => q.Categories)); 

以下是我收到的例外情况:

[AutoMapperConfigurationException:成员的自定义配置仅支持类型上的顶级个人成员。]

在与OP讨论之后,事实certificate他的主要需求是将源对象内的子/嵌套对象快速映射到展平的目标对象。 他不想为目的地的每个属性编写映射。

以下是实现此目的的方法:

  • 定义Product – > ProductViewModel用于展平Product的成员
  • 将映射Category定义为CategoryViewModel
  • 定义映射ProductWithCategories – > ProductViewModel ,映射类别,然后在aftermap中映射Product

    config.CreateMap() .ForMember(q => q.Id, option => option.Ignore()) // flattened in AfterMap .ForMember(q => q.Categories, option => option.MapFrom(q => q.Categories)) .AfterMap((src, dst) => Mapper.Map(src.Product, dst));

使用最新版本的AutoMapper,您可以执行以下操作:

 config.CreateMap() .ForMember(q => q.Categories, option => option.Ignore()); config.CreateMap() .ConstructUsing(s => AutoMapper.Mapper.Map(s.Product)) .ForMember(q => q.Categories, option => option.MapFrom(q => q.Categories)) .ForAllOtherMembers(o => o.Ignore(); 

ConstructUsing()用于从源的嵌套子[ren]生成和填充基类。 如果您有多个这样的嵌套子级,则需要进行多次映射调用,以便将它们中的每一个连续映射到第一个Map()调用生成的实例上。 .ForAllOtherMembers()是相对较新的(如果你没有它,请获取更新版本的AutoMapper。)不幸的是,它稍微不安全,好像你添加了需要映射但忘记更新地图的目标成员,配置validation不会抓住它。

产生错误的违规行是

 .ForMember(q => q, option => option.MapFrom(q => q.Product)) 

错误消息很难理解,但这意味着您必须明确声明目标属性:

 .ForMember(q => q.Id, option => option.MapFrom(q => q.Product.Id)) .ForMember(q => q.OtherProperty, option => option.MapFrom(q => q.Product.OtherProperty)) 

您还必须定义从CategoryCategoryViewModel的映射

 .ForMember(q => q.Categories, option => option.MapFrom(q => q.Categories)) 

上class:

 config.CreateMap(); 

你应该喜欢 –

 AutoMapper.Mapper.CreateMap(); AutoMapper.Mapper.CreateMap() .ForMember(a => a.Id, b => b.ResolveUsing(c => c.Product != null ? c.Product.MyProperty : 0)) .ForMember(a => a.Categories, b => b.ResolveUsing(c => c.Categories)); 

但最好将ProductViewModel (像Id这样的道具)中的那些属性包装在另一个类中。 并创建另一个地图,使事物以自动播放方式工作。