首页 > 解决方案 > 在对象图中查找所有类型的实例

问题描述

可以说我有以下对象图

Parent : BaseEntity
  string1 SimpleString
  Middle Middle
  List<Child> Children (3)

Middle : BaseEntity
  string NormalStr
  int NiceInt
  RandomClass Ignore

 Child : BaseEntity
   string ChildString
   Parent Parent
  

在这个例子中,我想要一种方法将我的 Parent 作为输入并返回一个平面列表 {Parent,Middle,Child1,Child2,Child3}。它应该适用于任何类型的对象图。

我试图通过反射和递归到达那里。我遇到的问题是 Parent 和 Child 之间的循环引用,我最终陷入了无限循环。

我该如何防止这种情况?我似乎无法让任何“已经看到”的机制起作用。

这是我到目前为止得到的。它可以在没有收集部分的情况下工作,但那部分非常重要......

    public void TraverseThroughProperties(object myObject)
    {
        foreach (var prop in myObject.GetType().GetProperties())
        {
            var instance = prop.GetValue(myObject);
            if (instance is BaseEntity myBase)
                TraverseThroughProperties(instance);


            if (instance is ICollection collection)
            {
                foreach (var item in collection.OfType<BaseEntity>())
                    TraverseThroughProperties(item);
            }

            // Do something with myObject + prop
        }
    }

标签: c#recursionreflection

解决方案


如果我正确理解了这个问题,我想最简单的方法是保留HashSet您访问过的类型。

public static void TraverseThroughProperties(object myObject, HashSet<Type> hashset = null)
{
   hashset ??= new HashSet<Type>();
   if (hashset.Contains(myObject.GetType()))
      return;
   hashset.Add(myObject.GetType());
   ...

注意:这可能不是最优的,因为它会拒绝相同的类型。另一种方法是保留访问的父子类型的元组。但是,这可能再次过滤超出预期。

public static void TraverseThroughProperties(object myObject, object parent, HashSet<(Type,Type)> hashset = null)
{
   hashset ??= new HashSet<(Type,Type)>();
   ...

另一种方法是散列实际参考。这将跟踪引用,或者再次跟踪父子引用

public static void TraverseThroughProperties(object myObject, HashSet<object> hashset = null)
{
   hashset ??= new HashSet<object>();
   if (hashset.Contains(myObject))
      return;
   hashset.Add(myObject);

虽然仍然可能不是您正在寻找和过滤的东西。然后这成为一个概念问题,您可能需要重新考虑您在做什么以及为什么。


推荐阅读