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

如何使用反射获取类及嵌套对象中所有名为Id的Guid属性及对应值

基于递归反射的实现方案

以下是可直接运行的实现,支持任意层级嵌套、泛型集合类型,自动过滤不符合要求的属性:

using System.Reflection;
using System.Collections;

public static class IdCollector
{
    // 存储已扫描过的类型的属性信息,避免重复反射查询,提升性能
    private static readonly Dictionary<Type, List<PropertyInfo>> _typePropertyCache = new();

    /// <summary>
    /// 递归收集对象树中所有名称为Id的Guid类型属性值
    /// </summary>
    /// <param name="target">要扫描的根对象实例</param>
    /// <returns>所有符合要求的Guid Id集合</returns>
    public static List<Guid> CollectAllGuidIds(object target)
    {
        var result = new List<Guid>();
        RecursiveCollect(target, result);
        return result;
    }

    private static void RecursiveCollect(object? target, List<Guid> result)
    {
        // 空对象直接跳过
        if (target == null) return;

        Type targetType = target.GetType();

        // 第一步:先处理当前对象的Id属性
        var idProp = targetType.GetProperty("Id", BindingFlags.Public | BindingFlags.Instance);
        if (idProp != null && idProp.PropertyType == typeof(Guid) && idProp.CanRead)
        {
            var idValue = (Guid)idProp.GetValue(target)!;
            result.Add(idValue);
        }

        // 第二步:获取当前类型的所有公共实例属性,优先读缓存
        if (!_typePropertyCache.TryGetValue(targetType, out var properties))
        {
            properties = targetType.GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList();
            _typePropertyCache[targetType] = properties;
        }

        foreach (var prop in properties)
        {
            // 跳过已处理的Id属性、不可读的属性
            if (prop.Name == "Id" || !prop.CanRead) continue;

            var propValue = prop.GetValue(target);
            if (propValue == null) continue;

            // 处理集合类型(排除字符串,因为字符串实现了IEnumerable<char>)
            if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) && prop.PropertyType != typeof(string))
            {
                var enumerator = ((IEnumerable)propValue).GetEnumerator();
                while (enumerator.MoveNext())
                {
                    RecursiveCollect(enumerator.Current, result);
                }
            }
            // 处理自定义类类型,跳过基础值类型、枚举、字符串等不需要递归的类型
            else if (prop.PropertyType.IsClass && prop.PropertyType != typeof(string))
            {
                RecursiveCollect(propValue, result);
            }
        }
    }
}

调用示例

// 构造测试数据
var main = new Main
{
    Id = Guid.NewGuid(),
    Children = new List<Child>
    {
        new Child
        {
            Id = Guid.NewGuid(),
            GrandChildren = new List<GrandChild>
            {
                new GrandChild{ Id = Guid.NewGuid() },
                new GrandChild{ Id = Guid.NewGuid() }
            }
        },
        new Child{ Id = Guid.NewGuid() }
    }
};

// 收集所有Id
var allIds = IdCollector.CollectAllGuidIds(main);
// 最终输出结果共5个Id:1个Main类Id、2个Child类Id、2个GrandChild类Id

可选优化说明

  • 如果你需要保留Id对应的对象层级路径,可以把返回值改成List<(string Path, Guid Id)>,递归的时候拼接路径信息即可
  • 内置的类型属性缓存可以大幅降低高频调用场景下的反射开销
  • 支持所有实现了IEnumerable接口的泛型/非泛型集合,无需单独适配
  • 自动处理空值场景,不会触发空引用异常

内容的提问来源于stack exchange,提问作者lolo xoxo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 11:06:08