【问题标题】:Find all instances of Type in an object graph在对象图中查找所有类型的实例
【发布时间】:2021-01-04 21:21:41
【问题描述】:

假设我有以下对象图

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
        }
    }

【问题讨论】:

  • 从你的对象中不清楚你需要递归的地方。您的 BaseEntity 类是否提供了一些抽象接口,允许您将这些类视为图形?唯一引用层次结构中其他类的实例是 Parent,展平单个父级将相当简单,根本不需要递归。

标签: c# recursion reflection


【解决方案1】:

如果我正确理解了这个问题,我想最简单的方法是保留您访问过的类型的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);

虽然仍然可能不是您想要的并且过滤太多。这将成为一个概念问题,您可能需要重新考虑您在做什么以及为什么这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    • 2014-11-19
    • 1970-01-01
    • 2015-12-20
    • 2014-04-28
    • 2011-10-16
    • 1970-01-01
    相关资源
    最近更新 更多