【问题标题】:Recursive routine to obtain PropertyInfo获取 PropertyInfo 的递归例程
【发布时间】:2011-12-27 01:37:06
【问题描述】:

我正在尝试创建一个递归例程,它将检索指定对象下所有成员的 PropertyInfos(在 .NET 3.5 中)。直接成员的一切都在工作,但它还需要解析嵌套类(以及它们的嵌套类等)。

我不明白如何处理解析嵌套类的部分。这部分代码你会怎么写?

public class ObjectWalkerEntity
{
    public object Value { get; set; }
    public PropertyInfo PropertyInfo { get; set; }
}


public static class ObjectWalker
{
    // This will be the returned object
    static List<ObjectWalkerEntity> objectList = new List<ObjectWalkerEntity>();

    public static List<ObjectWalkerEntity> Walk(object o)
    {
        objectList.Clear();
        processObject(o);
        return objectList;
    }

    private static void processObject(object o)
    {
        if (o == null)
        {
            return;
        }

        Type t = o.GetType();

        foreach (PropertyInfo pi in t.GetProperties())
        {
            if (isGeneric(pi.PropertyType))
            {
                // Add generic object
                ObjectWalkerEntity obj = new ObjectWalkerEntity();
                obj.PropertyInfo = pi;
                obj.Value = pi.GetValue(o, null);
                objectList.Add(obj);
            }
            else
            {
                ////// TODO: Find a way to parse the members of the subclass...
                // Parse each member of the non-generic object
                foreach (Object item in pi.PropertyType)
                {
                    processObject(item);
                }
            }
        }

        return;
    }

    private static bool isGeneric(Type type)
    {
        return
            Extensions.IsSubclassOfRawGeneric(type, typeof(bool)) ||
            Extensions.IsSubclassOfRawGeneric(type, typeof(string)) ||
            Extensions.IsSubclassOfRawGeneric(type, typeof(int)) ||
            Extensions.IsSubclassOfRawGeneric(type, typeof(UInt16)) ||
            Extensions.IsSubclassOfRawGeneric(type, typeof(UInt32)) ||
            Extensions.IsSubclassOfRawGeneric(type, typeof(UInt64)) ||
            Extensions.IsSubclassOfRawGeneric(type, typeof(DateTime));
    }

编辑:我采用了 Harlam 的一些建议,并提出了一个可行的解决方案。这处理嵌套类和列表。

我已经用以下内容替换了我之前通过 propertyinfo 的循环

foreach (PropertyInfo pi in t.GetProperties())
{
    if (isGeneric(pi.PropertyType))
    {
        // Add generic object
        ObjectWalkerEntity obj = new ObjectWalkerEntity();
        obj.PropertyInfo = pi;
        obj.Value = pi.GetValue(o, null);
        objectList.Add(obj);
    }
    else if (isList(pi.PropertyType))
    {
        // Parse the list
        var list = (IList)pi.GetValue(o, null);
        foreach (object item in list)
        {
            processObject(item);
        }
    }
    else
    {
        // Parse each member of the non-generic object
        object value = pi.GetValue(o, null);
        processObject(value);
    }
}

我还添加了一项新检查,以查看某项是否为列表。

private static bool isList(Type type)
{
    return
        IsSubclassOfRawGeneric(type, typeof(List<>));
}

感谢您的帮助!

【问题讨论】:

    标签: c# reflection .net-3.5 recursion


    【解决方案1】:

    看看Devscribe。它是开源的,使用 Reflection 来迭代每个反射类型——包括处理泛型。

    【讨论】:

      【解决方案2】:

      我认为这对你有用。这里的想法是从每次调用 ProcessObject() 返回一个可枚举对象,然后将这些调用汇总到调用者 List&lt;ObjectWalkerEntity&gt;

      public class ObjectWalkerEntity
      {
         public object Value { get; set; }
         public PropertyInfo PropertyInfo { get; set; }
      }
      
      public static class ObjectWalker
      {
         public static List<ObjectWalkerEntity> Walk(object o)
         {
            return ProcessObject(o).ToList();
         }
      
         private static IEnumerable<ObjectWalkerEntity> ProcessObject(object o)
         {
            if (o == null)
            {
               // nothing here, just return an empty enumerable object
               return new ObjectWalkerEntity[0];
            }
      
            // create the list to hold values found in this object
            var objectList = new List<ObjectWalkerEntity>();
      
            Type t = o.GetType();
            foreach (PropertyInfo pi in t.GetProperties())
            {
               if (IsGeneric(pi.PropertyType))
               {
                  // Add generic object
                  var obj = new ObjectWalkerEntity();
                  obj.PropertyInfo = pi;
                  obj.Value = pi.GetValue(o, null);
                  objectList.Add(obj);
               }
               else
               {
                  // not generic, get the property value and make the recursive call
                  object value = pi.GetValue(o, null);
                  // all values returned from the recursive call get 
                  // rolled up into the list created in this call.
                  objectList.AddRange(ProcessObject(value));
               }
            } 
      
            return objectList.AsReadOnly();
         }
      
         private static bool IsGeneric(Type type)
         {
            return
                IsSubclassOfRawGeneric(type, typeof(bool)) ||
                IsSubclassOfRawGeneric(type, typeof(string)) ||
                IsSubclassOfRawGeneric(type, typeof(int)) ||
                IsSubclassOfRawGeneric(type, typeof(UInt16)) ||
                IsSubclassOfRawGeneric(type, typeof(UInt32)) ||
                IsSubclassOfRawGeneric(type, typeof(UInt64)) ||
                IsSubclassOfRawGeneric(type, typeof(DateTime));
         }
      
         private static bool IsSubclassOfRawGeneric(Type generic, Type toCheck)
         {
            while (toCheck != typeof(object))
            {
               var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
               if (generic == cur)
               {
                  return true;
               }
               toCheck = toCheck.BaseType;
            }
            return false;
         }
      }
      

      【讨论】:

      • 可以使用 yield return 并且还应该保存一个已处理对象的列表以用于反向引用属性。
      • 这几乎可以工作,但它遇到了列表问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-23
      • 2016-10-29
      • 2019-01-08
      • 2012-05-14
      相关资源
      最近更新 更多