递归例程以获取PropertyInfo [英] Recursive routine to obtain PropertyInfo

查看:96
本文介绍了递归例程以获取PropertyInfo的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm attempting to create a recursive routine that will retrieve PropertyInfos for all members under a specified object (in .NET 3.5). Everything for immediate members is working, but it needs to parse nested classes as well (and their nested classes, etc).

我不知道如何处理该部分解析嵌套类。您将如何编写这部分代码?

I do not understand how to handle the section that parses nested classes. How would you write this part of the code?

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的一些建议,并提出了可行的解决方案。这将处理嵌套的类和列表。

I've used some of Harlam's suggestions, and came up with a working solution. This handles both nested classes and lists.

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

I've replaced my previous loop through the propertyinfo with the following

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

我还添加了新的检查以查看是否

I've also added a new check to see if something is a list.

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

感谢您的帮助!

推荐答案

我认为这对您有用。这里的想法是从每次调用 ProcessObject()返回一个可枚举的对象,然后将这些调用汇总到调用方 List< ObjectWalkerEntity>

I think this will work for you. The idea here is to return an enumerable object from each call to ProcessObject() and then roll those calls up into the callers List<ObjectWalkerEntity>.

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

这篇关于递归例程以获取PropertyInfo的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆