[英]How to use AutoMapper to map destination object with a child object in the source object?
我有这样的源和目标对象:
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; }
}
所以,我需要的是的值映射source.Product
到dest
然后和source.Categories
到dest.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));
以下是我收到的例外情况:
[AutoMapperConfigurationException:成员的自定义配置仅支持某个类型的顶级个人成员。]
在与OP讨论之后,事实证明他的主要需求是快速将源对象内的子/嵌套对象映射到展平的目标对象。 他不想为目的地的每个属性编写映射。
这是实现此目的的一种方法:
Product
- > ProductViewModel
用于展平Product的成员 Category
定义为CategoryViewModel
定义一个映射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));
使用最新版本的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();
ConstructUsing()用于从源的嵌套子[ren]生成和填充基类。 如果您有多个这样的嵌套子级,则需要进行多次映射调用,将其中的每一个连续映射到第一次Map()调用生成的实例上。 .ForAllOtherMembers()是相对较新的(如果您没有它,请获取更新版本的AutoMapper。)不幸的是,它稍微不安全,就好像您添加了需要映射但忘记更新地图的目标成员,配置验证不会抓住它。
你应该喜欢 -
AutoMapper.Mapper.CreateMap<Category, CategoryViewModel>();
AutoMapper.Mapper.CreateMap<ProductWithCategories, ProductViewModel>()
.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
这样的道具)中的那些属性包装在另一个类中。 并创建另一个地图,使事物以自动播放方式工作。
产生错误的违规行是
.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))
您还必须定义从Category
到CategoryViewModel
的映射
.ForMember(q => q.Categories, option => option.MapFrom(q => q.Categories))
上班:
config.CreateMap<Category, CategoryViewModel>();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.