如何结合Linq Zip与AutoMapper实现多对象映射?
问题:用AutoMapper结合Linq实现A、B到C的合并映射
现有类定义:
class A { public string FirstName { get; set; } public string LastName { get; set; } public int ForeinKey { get; set; } // 补充原循环逻辑中用到的外键字段 } class B { public int Id { get; set; } // 补充原循环逻辑中用到的关联Id字段 public DateTime TimeOfBirth { get; set; } } // A & B 合并类 class C { public string FirstName { get; set; } public string LastName { get; set; } public DateTime TimeOfBirth { get; set; } }
当前通过循环实现的逻辑:先将A实例映射为C,再通过外键匹配对应的B实例,将B的字段合并到同一个C实例中:
List<C> output = new(); foreach (var a in listA) { C result = _mapper.Map<C>(a); _mapper.Map<B, C>(listB.Single(b => b.Id == a.ForeinKey), result); output.Add(result); }
尝试用Linq Zip实现但编译失败:
var output = _mapper.Map<C>(listA).Zip(_mapper.Map<C>(listB));
解决方案
核心问题分析
你尝试的Zip写法存在两个关键错误:
- 类型不匹配:
_mapper.Map<C>(listA)传入的是List<A>集合,却要求映射为单个C对象,AutoMapper无法完成这个转换,正确的集合映射应该是_mapper.Map<List<C>>(listA)。 - 逻辑错误:即使修正映射,Zip只会将两个
C对象按索引配对,无法实现「合并成单个包含A+B字段的C」的需求;更重要的是,你原逻辑是通过外键关联A和B,而非按集合顺序配对,这种场景下Zip并不适用。
分场景处理
场景1:A和B集合按索引一一对应(顺序匹配)
如果listA和listB中相同位置的元素是一组对应关系,可以用Zip结合AutoMapper实现:
// 确保已配置A→C、B→C的AutoMapper映射 var output = listA.Zip(listB, (a, b) => { // 先将A映射为C var c = _mapper.Map<C>(a); // 再将B的字段合并到C中 _mapper.Map(b, c); return c; }).ToList();
场景2:按外键关联A和B(与原循环逻辑一致)
这种场景下应该用Linq的Join来关联两个集合,再完成映射:
var output = listA.Join( listB, a => a.ForeinKey, // A的关联键 b => b.Id, // B的关联键 (a, b) => { var c = _mapper.Map<C>(a); _mapper.Map(b, c); return c; } ).ToList();
补充AutoMapper配置示例
需要提前配置好A到C、B到C的映射规则:
var mapperConfig = new MapperConfiguration(cfg => { cfg.CreateMap<A, C>(); // 自动映射同名字段 cfg.CreateMap<B, C>(); }); var _mapper = mapperConfig.CreateMapper();
内容的提问来源于stack exchange,提问作者Jakob Busk Sørensen
相关产品推荐
相关产品推荐

