基于属性值从嵌套对象提取实例并映射到新类的最优方案
解决方案:嵌套对象筛选+映射(含AutoMapper实现)
针对你的需求——从嵌套的MessageViewModel结构中提取所有IsSelected = true的实例并转换为DestinationClass,这个场景完全可以用AutoMapper实现,最优方案是先递归遍历筛选符合条件的对象,再结合AutoMapper完成类型转换,下面分步骤说明:
1. 核心:递归遍历嵌套结构
首先需要解决的是遍历整个嵌套的MessageViewModel树,筛选出IsSelected为true的实例。你自己实现的TraversalHelper思路是对的,不过可以优化成直接返回筛选后的集合,代码更简洁:
public static class TraversalHelper { // 递归遍历整个嵌套结构,返回所有节点 public static IEnumerable<T> Traverse<T>(this T root, Func<T, IEnumerable<T>> getChildren) where T : class { if (root == null) yield break; yield return root; // 获取子节点,为空则返回空集合 var children = getChildren(root) ?? Enumerable.Empty<T>(); foreach (var child in children) { // 递归遍历子节点并返回 foreach (var item in child.Traverse(getChildren)) { yield return item; } } } }
使用这个工具类,你可以轻松筛选出所有符合条件的实例:
var vm = new MessageViewModel { Messages = new List<MessageViewModel> { new MessageViewModel { IsSelected = true, Messages = new List<MessageViewModel> { new MessageViewModel { IsSelected = true, Messages = new List<MessageViewModel> { new MessageViewModel { }, new MessageViewModel { }, new MessageViewModel { } } } } } } }; // 遍历所有节点并筛选IsSelected=true的实例 var selectedMessages = vm.Traverse(m => m.Messages).Where(m => m.IsSelected);
2. 结合AutoMapper实现类型转换
接下来可以用AutoMapper来完成MessageViewModel到DestinationClass的映射,步骤如下:
第一步:配置AutoMapper映射规则
因为两个类的Subject属性名称一致,AutoMapper会自动完成匹配,无需额外配置:
// 初始化AutoMapper配置 var mapperConfig = new MapperConfiguration(cfg => { cfg.CreateMap<MessageViewModel, DestinationClass>(); }); IMapper mapper = mapperConfig.CreateMapper();
第二步:批量转换筛选后的实例
直接用Select结合AutoMapper的Map方法即可完成批量转换:
var destinationList = selectedMessages.Select(mapper.Map<DestinationClass>).ToList();
3. 你的原始实现说明
你自己写的TraversalHelper是可行的,通过Action来收集结果的方式也能达到目的。如果不需要AutoMapper,直接在Action里手动创建DestinationClass实例也是完全没问题的:
var results = new List<DestinationClass>(); vm.TraverseAndExecute(_ => _.Messages, _ => { if(_.IsSelected == true) { results.Add(new DestinationClass { Subject = _.Subject }); } });
总结
- 如果你的映射逻辑简单,手动映射和AutoMapper都可以;但如果后续类的属性有变化,AutoMapper的维护性更好,不需要修改映射代码。
- 递归遍历嵌套结构是这个需求的核心,不管用不用AutoMapper都需要这一步。
内容的提问来源于stack exchange,提问作者Radu Olteanu
相关产品推荐
相关产品推荐

