如何使用AutoMapper按父对象条件映射子DTO的RunEt属性值
问题根因
- 你现有配置的核心问题是
CreateMap<Pair, QualifyingPairDto>的链式调用语法不完整,两个ForMember配置结束后没有续接后续的ForPath/AfterMap配置,且末尾缺少分号,导致附加配置未生效。 - 子对象
QualifyingRunDto的RunEt字段在Run类中没有同名对应属性,默认映射规则下自然赋值为null,需要显式配置赋值逻辑。 - 你现有配置仅处理了左车道的
RunEt,右车道没有对应配置。
解决方案
不需要自定义值解析器,以下两种常用实现方式均可满足需求:
方案1:使用AfterMap(最直观,适合复杂分支逻辑)
直接在Pair到QualifyingPairDto的映射中补全AfterMap配置,同时处理左右车道,增加空校验避免异常:
public MappingProfiles() { CreateMap<Event, Event>(); CreateMap<EventMaster, EventMaster>(); CreateMap<Track, Track>(); CreateMap<Event, EventDto>() .ForMember(d => d.Name, o => o.MapFrom(s => s.EventEm.Name)) .ForMember(d => d.Track, o => o.MapFrom(s => s.EventEm.Track)); CreateMap<Run, QualifyingRunDto>(); CreateMap<Pair, QualifyingPairDto>() .ForMember(d => d.LeftLane, o => o.MapFrom(s => s.Runs.FirstOrDefault(r => r.RunLane == 1))) .ForMember(d => d.RightLane, o => o.MapFrom(s => s.Runs.FirstOrDefault(r => r.RunLane == 2))) .AfterMap((src, dest) => { // 处理左车道属性 if (dest.LeftLane != null) { var leftRun = src.Runs.FirstOrDefault(r => r.RunLane == 1); if (leftRun != null) { dest.LeftLane.RunEt = src.PairFinish switch { 1 => leftRun.RunEt1320, 2 => leftRun.RunEt1000, 3 => leftRun.RunEt660, _ => null }; // 可同步补充RunSp的赋值逻辑 dest.LeftLane.RunSp = src.PairFinish switch { 1 => leftRun.RunSp1320, 2 => leftRun.RunSp1000, 3 => leftRun.RunSp660, _ => null }; } } // 处理右车道属性 if (dest.RightLane != null) { var rightRun = src.Runs.FirstOrDefault(r => r.RunLane == 2); if (rightRun != null) { dest.RightLane.RunEt = src.PairFinish switch { 1 => rightRun.RunEt1320, 2 => rightRun.RunEt1000, 3 => rightRun.RunEt660, _ => null }; dest.RightLane.RunSp = src.PairFinish switch { 1 => rightRun.RunSp1320, 2 => rightRun.RunSp1000, 3 => rightRun.RunSp660, _ => null }; } } }); }
方案2:使用ForPath(适合单字段简单赋值)
如果仅需要赋值RunEt字段,也可以用ForPath实现:
CreateMap<Pair, QualifyingPairDto>() .ForMember(d => d.LeftLane, o => o.MapFrom(s => s.Runs.FirstOrDefault(r => r.RunLane == 1))) .ForMember(d => d.RightLane, o => o.MapFrom(s => s.Runs.FirstOrDefault(r => r.RunLane == 2))) // 左车道RunEt .ForPath(d => d.LeftLane.RunEt, o => o.MapFrom((src, _) => { var leftRun = src.Runs.FirstOrDefault(r => r.RunLane == 1); if(leftRun == null) return null; return src.PairFinish switch { 1 => leftRun.RunEt1320, 2 => leftRun.RunEt1000, 3 => leftRun.RunEt660, _ => null }; })) // 右车道RunEt .ForPath(d => d.RightLane.RunEt, o => o.MapFrom((src, _) => { var rightRun = src.Runs.FirstOrDefault(r => r.RunLane == 2); if(rightRun == null) return null; return src.PairFinish switch { 1 => rightRun.RunEt1320, 2 => rightRun.RunEt1000, 3 => rightRun.RunEt660, _ => null }; }));
注意事项
不要直接使用First()方法,建议用FirstOrDefault()配合空校验,避免Runs集合中没有对应车道数据时抛出序列空异常。如果相同的RunEt赋值逻辑需要在多个映射场景复用,可以再考虑自定义值解析器,否则上述两种方案已经足够满足需求。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

