C# 如何枚举给定根对象的所有可访问对象?
我想实现一个方法,该方法接收根对象并返回一个列表,其中包含从根对象开始可以访问的所有对象的引用。其签名如下:C# 如何枚举给定根对象的所有可访问对象?,c#,reflection,reference,C#,Reflection,Reference,我想实现一个方法,该方法接收根对象并返回一个列表,其中包含从根对象开始可以访问的所有对象的引用。其签名如下: static List<object> EnumerateObjectsInRange(object root); 静态列表EnumerateObjectsRange(对象根); 我正在考虑使用检索对象数组,然后使用获取这些属性的值,最后再次调用每个值,并重复此过程,直到访问了整个对象图,但我不确定这是否是最佳方法 有什么建议吗 编辑: 我可以想出两个关于可达性的定义:
static List<object> EnumerateObjectsInRange(object root);
静态列表EnumerateObjectsRange(对象根);
我正在考虑使用检索对象数组,然后使用获取这些属性的值,最后再次调用每个值,并重复此过程,直到访问了整个对象图,但我不确定这是否是最佳方法
有什么建议吗
编辑:
我可以想出两个关于可达性的定义:
第一个定义对于我来说已经足够了。您肯定需要字段,而不是属性。对象通过字段而不是属性使其他对象保持活动状态。您不需要创建特殊的案例列表,因为它们包含一个内部数组,您可以使用GetFields找到该数组。但是,您需要使用特殊情况数组
顺便说一句,我已经实现了这个算法,并且发现它是有效的和有用的。为了防止有人发现它有用,我正在分享一个递归方法,我从usr和Henk的答案中写下,解决了我的问题:
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,这超出了我的范围。