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

Luk*_* Vo 11 c# entity-framework automapper

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

class ProductWithCategories // Source class
{
    public Product Product { get; set; } // Product is an EF entity class
    public IEnumerable<Category> Categories { get; set; }
}

class ProductViewModel // Dest class
{
    public int Id { get; set; }
    // Other properties with the same name as Product class

    public IEnumerable<CategoryViewModel> Categories { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

所以,我需要将值映射source.Productdest,然后映射source.Categoriesdest.Categories.AutoMapper有可能吗?

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

        config.CreateMap<ProductWithCategories, ProductViewModel>()
            .ForMember(q => q, option => option.MapFrom(q => q.Product))
            .ForMember(q => q.Categories, option => option.MapFrom(q => q.Categories));
Run Code Online (Sandbox Code Playgroud)

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

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

Geo*_*der 27

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

这是实现此目的的一种方法:

  • 定义映射Product- > ProductViewModel用于展平Product的成员
  • 定义映射CategoryCategoryViewModel
  • 定义映射ProductWithCategories- > ProductViewModel映射类别,然后在aftermap中映射Product:

    config.CreateMap<ProductWithCategories, ProductViewModel>() .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));

  • 是的,您可以在 Cliff 的回答中添加评论。您需要 5.x 版本的 Automapper 来完成它。 (2认同)

小智 11

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

config.CreateMap<Product, ProductViewModel>()
      .ForMember(q => q.Categories, option => option.Ignore());

config.CreateMap<ProductWithCategories, ProductViewModel>()
      .ConstructUsing(s => AutoMapper.Mapper.Map<ProductViewModel>(s.Product))
      .ForMember(q => q.Categories, option => option.MapFrom(q => q.Categories))
      .ForAllOtherMembers(o => o.Ignore();
Run Code Online (Sandbox Code Playgroud)

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

  • 仅适用于使用基于实例的初始化的人,更改为`.ConstructUsing((s,ctx)=> ctx.Mapper.Map <ProductViewModel>(s.Product))`.您可以在ResolutionContext上访问运行​​时映射器. (8认同)