C# 如何枚举给定根对象的所有可访问对象?

C# 如何枚举给定根对象的所有可访问对象?,c#,reflection,reference,C#,Reflection,Reference,我想实现一个方法,该方法接收根对象并返回一个列表,其中包含从根对象开始可以访问的所有对象的引用。其签名如下: static List<object> EnumerateObjectsInRange(object root); 静态列表EnumerateObjectsRange(对象根); 我正在考虑使用检索对象数组,然后使用获取这些属性的值,最后再次调用每个值,并重复此过程,直到访问了整个对象图,但我不确定这是否是最佳方法 有什么建议吗 编辑: 我可以想出两个关于可达性的定义:

我想实现一个方法,该方法接收根对象并返回一个列表,其中包含从根对象开始可以访问的所有对象的引用。其签名如下:

static List<object> EnumerateObjectsInRange(object root);
静态列表EnumerateObjectsRange(对象根);
我正在考虑使用检索对象数组,然后使用获取这些属性的值,最后再次调用每个值,并重复此过程,直到访问了整个对象图,但我不确定这是否是最佳方法

有什么建议吗

编辑:

我可以想出两个关于可达性的定义:

  • 根对象的所有者能够访问的所有对象(公共可用对象)
  • 根对象所属的对象图引用的所有公共和私有对象

  • 第一个定义对于我来说已经足够了。

    您肯定需要字段,而不是属性。对象通过字段而不是属性使其他对象保持活动状态。您不需要创建特殊的案例列表,因为它们包含一个内部数组,您可以使用GetFields找到该数组。但是,您需要使用特殊情况数组


    顺便说一句,我已经实现了这个算法,并且发现它是有效的和有用的。

    为了防止有人发现它有用,我正在分享一个递归方法,我从usrHenk的答案中写下,解决了我的问题:

    static void EnumerateObjectsInRange(object root, HashSet<object> hashset)
    {
        if (root == null || hashset.Contains(root))
        {
            return;
        }
    
        hashset.Add(root);
        FieldInfo[] fields = root.GetType().GetFields(BindingFlags.Static
                                                    | BindingFlags.Instance
                                                    | BindingFlags.Public
                                                    | BindingFlags.NonPublic);
    
        foreach (FieldInfo field in fields)
        {
            object obj = field.GetValue(root);
    
            if (obj == null)
            {
                continue;
            }
    
            if (obj.GetType().IsSubclassOf(typeof(Array)))
            {
                foreach (object member in (Array)obj)
                {
                    EnumerateObjectsInRange(member, hashset);
                }
            }
    
            EnumerateObjectsInRange(obj, hashset);
        }
    }
    
    static void EnumerateObjectsInRange(对象根,HashSet HashSet)
    {
    if(root==null | | hashset.Contains(root))
    {
    返回;
    }
    添加(根);
    FieldInfo[]fields=root.GetType().GetFields(BindingFlags.Static
    |BindingFlags.Instance
    |BindingFlags.Public
    |BindingFlags(非公开);
    foreach(字段中的字段信息字段)
    {
    object obj=field.GetValue(根);
    if(obj==null)
    {
    继续;
    }
    if(obj.GetType().IsSubclassOf(typeof(数组)))
    {
    foreach(数组obj中的对象成员)
    {
    EnumerateObjectsInRange(成员,哈希集);
    }
    }
    EnumerateObjectsInRange(obj,哈希集);
    }
    }
    
    这个方法仍然需要一些重构(它不检查HashSet是否为null),但它完成了任务


    要调用它,请提供根对象和一个空哈希集,在其中存储访问的对象。

    您需要一个递归算法。基本上,这就像BF搜索。要获得更多/更好的建议,您必须指出它的用途以及“可访问”的确切含义。由于您自己实现了此算法,您能告诉我数组是否是我将找到的唯一特例吗?:)是的。您只需要考虑可以存储对其他对象的引用的“事物”。只有字段和数组可以这样做。它们可以容纳任何东西,这无关紧要。它们将仅引用使用字段的其他对象。它们的实施细节并不重要。如果需要示例,请考虑链表或哈希表的内部外观。只是场上。很好的尝试,但离理想还很远。有很多事情需要特别处理。例如,值类型字段、重写Equals()和GetHashCode()方法的类、从另一个AppDomain代理的对象等。感谢您的提示。我想出了一个解决方案来处理Equals()和GetHashCode()使用一个函数为不同的对象返回相同的值的情况,我只是忽略了值类型字段,因为您无法获取对它们的引用,只能获取副本(但我仍在查看它们是否包含引用类型字段)。关于AppDomains,这超出了我的范围。