递归例程获取PropertyInfo

2024-06-20

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

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

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

Edit:我采纳了 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<>));
}

谢谢您的帮助!


我认为这对你有用。这里的想法是从每次调用返回一个可枚举对象ProcessObject()然后将这些呼叫转给呼叫者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;
   }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

递归例程获取PropertyInfo 的相关文章

  • 如何读取扩展文件属性/文件元数据

    因此 我按照教程使用 ASP net core 将文件 上传 到本地路径 这是代码 public IActionResult About IList
  • C++ 中本地类中的静态成员变量?

    我知道我们不能宣布static本地类中的成员变量 但其原因尚不清楚 那么请问有人可以解释一下吗 另外 为什么我们不能访问非static函数内部定义的变量 内部已经定义了局部类 直接在局部类成员函数中 在下面给出的代码中 int main i
  • Unix网络编程澄清

    我正在翻阅这本经典书籍Unix网络编程 https rads stackoverflow com amzn click com 0139498761 当我偶然发现这个程序时 第 6 8 节 第 179 180 页 include unp h
  • 为 Visual Studio 2013 编译 Tesseract

    我正在尝试使用tesseract在 Visual Studio 2013 中 我在链接器 gt 输入 不是 libtesseract302 static lib 中使用 libtesseract302 lib 一切都正常 并且已编译并运行
  • 向 Nhibernate 发出 SQL 查询

    如何将此 SQL 查询发送给 Nhibernate SELECT Customer name FROM Company INNER JOIN Customer ON Company CompanyId Customer CompanyId
  • 如何修复此错误“GDI+ 中发生一般错误”?

    从默认名称打开图像并以默认名称保存 覆盖它 我需要从 Image Default jpg 制作图形 将其放在 picturebox1 image 上并在 picurebox1 上绘制一些图形 它有效 这不是我的问题 但我无法保存 pictu
  • 互斥体实现可以互换(独立于线程实现)

    所有互斥体实现最终都会调用相同的基本系统 硬件调用吗 这意味着它们可以互换吗 具体来说 如果我使用 gnu parallel算法 使用openmp 并且我想让他们称之为线程安全的类我可以使用boost mutex用于锁定 或者我必须编写自己
  • 单元测试一起运行时失败,单独运行时通过

    所以我的单元测试遇到了一些问题 我不能只是将它们复制并粘贴到这里 但我会尽力而为 问题似乎是 如果我一项一项地运行测试 一切都会按预期进行 但如果我告诉它一起运行测试 则 1 5 将通过 TestMethod public void Obj
  • 如何在 C# 中定义文本框数组?

    您好 当我在 Windows 申请表上创建文本框时 我无法将其命名为 box 0 box 1 等 我这样做的目的是因为我想循环使用它们 其实我发现TextBox array firstTextBox secondTextBox 也有效
  • 获取 WPF 控件的所有附加事件处理程序

    我正在开发一个应用程序 在其中动态分配按钮的事件 现在的问题是 我希望获取按钮单击事件的所有事件 因为我希望删除以前的处理程序 我尝试将事件处理程序设置为 null 如下所示 Button Click null 但是我收到了一个无法分配 n
  • 单击 form2 上的按钮触发 form 1 中的方法

    我对 Windows 窗体很陌生 我想知道是否可以通过单击表单 2 中的按钮来触发表单 1 中的方法 我的表格 1 有一个组合框 我的 Form 2 有一个 保存 按钮 我想要实现的是 当用户单击表单 2 中的 保存 时 我需要检查表单 1
  • 在一个字节中存储 4 个不同的值

    我有一个任务要做 但我不知道从哪里开始 我不期待也绝对不想要代码中的答案 我想要一些关于该怎么做的指导 因为我感到有点失落 将变量打包和解包到一个字节中 您需要在一个字节中存储 4 个不同的值 这些值为 NAME RANGE BITS en
  • PlaySound 可在 Visual Studio 中运行,但不能在独立 exe 中运行

    我正在尝试使用 Visual Studio 在 C 中播放 wav 文件 我将文件 my wav 放入项目目录中并使用代码 PlaySound TEXT my wav NULL SND FILENAME SND SYNC 我按下播放按钮 或
  • 如何在 Blackberry Cascades 中显示具有特定号码的电话板

    我正在使用带有 C QT 和 QML 的 Blackberry Cascades 10 Beta 3 SDK 以及 Blackberry 10 Dev Alpha Simulator 和 QNX Momentics IDE 并且我正在尝试实
  • 等待线程完成

    private void button1 Click object sender EventArgs e for int i 0 i lt 15 i Thread nova new Thread Method nova Start list
  • C++ 密码屏蔽

    我正在编写一个代码来接收密码输入 下面是我的代码 程序运行良好 但问题是除了数字和字母字符之外的其他键也被读取 例如删除 插入等 我知道如何避免它吗 特q string pw char c while c 13 Loop until Ent
  • 为什么在setsid()之前fork()

    Why fork before setsid 守护进程 基本上 如果我想将一个进程与其控制终端分离并使其成为进程组领导者 我使用setsid 之前没有分叉就这样做是行不通的 Why 首先 setsid 将使您的进程成为进程组的领导者 但它也
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 如何将 Roslyn 语义模型返回的类型符号名称与 Mono.Cecil 返回的类型符号名称相匹配?

    我有以下代码 var paramDeclType m semanticModel GetTypeInfo paramDecl Type Type Where paramDeclType ToString returns System Col
  • 如何使用 Word Automation 获取页面范围

    如何使用办公自动化找到 Microsoft Word 中第 n 页的范围 似乎没有 getPageRange n 函数 并且不清楚它们是如何划分的 这就是您从 VBA 执行此操作的方法 转换为 Matlab COM 调用应该相当简单 Pub

随机推荐