如何使用AutoMapper映射/展平第三方API返回的三级属性?
解决AutoMapper映射三级属性/嵌套集合的问题
这个问题我之前也碰到过,核心是AutoMapper处理集合映射时需要先搞定单个元素的转换规则,而不是直接试图操作集合的二级属性。咱们一步步来解决:
1. 先明确类型对应关系(补全你没写全的源类型)
假设你的源类型结构大概是这样的:
public class Source { public List<SourceSmartLink> Smartlink { get; set; } } public class SourceSmartLink { public Address Address { get; set; } }
目标类型就是你给出的:
public class Parent { public List<SmartLink> SmartLink { get; set; } } public class SmartLink { public AddressInfo AddressInfo { get; set; } }
2. 正确的映射配置步骤
第一步:配置基础类型映射
先把最底层的Address到AddressInfo的映射配好,你这步已经做对了:
cfg.CreateMap<Address, AddressInfo>();
第二步:配置集合元素的映射
关键就在这一步!你需要告诉AutoMapper如何把单个SourceSmartLink转换成SmartLink:
cfg.CreateMap<SourceSmartLink, SmartLink>() .ForMember(dest => dest.AddressInfo, opt => opt.MapFrom(src => src.Address));
这一步会让AutoMapper知道,每个源集合项里的Address要映射到目标集合项的AddressInfo。
第三步:配置根对象的映射
最后配置Source到Parent的映射,直接映射整个集合即可,AutoMapper会自动用上面的规则处理每个元素:
cfg.CreateMap<Source, Parent>() .ForMember(dest => dest.SmartLink, opt => opt.MapFrom(src => src.Smartlink.ToList()));
3. 为什么你原来的写法不行?
你之前尝试的:
.ForMember(d => d.SmartLink.AddressInfo, map => map.MapFrom(src => src.Smartlink.ToList().Select(addr => addr.Address)));
这里的问题在于d.SmartLink是一个List<SmartLink>集合,它本身并没有AddressInfo属性——只有集合里的每个SmartLink对象才有这个属性。AutoMapper无法直接对集合的"二级属性"做批量映射,必须先定义单个元素的转换规则,再让它自动处理集合。
4. 替代方案:直接投影构造对象
如果不想单独配置SourceSmartLink到SmartLink的映射,也可以在根映射里直接构造目标对象:
cfg.CreateMap<Source, Parent>() .ForMember(dest => dest.SmartLink, opt => opt.MapFrom(src => src.Smartlink.Select(sl => new SmartLink { AddressInfo = Mapper.Map<AddressInfo>(sl.Address) }).ToList()));
不过这种方式的缺点是,当SmartLink后续新增其他属性时,你需要手动修改这段代码,不如单独配置元素映射的方式易维护。
内容的提问来源于stack exchange,提问作者Felix Too
相关产品推荐
相关产品推荐

