You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于属性值从嵌套对象提取实例并映射到新类的最优方案

解决方案:嵌套对象筛选+映射(含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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:07:29