反射 - 在我自己的程序集中递归迭代对象的属性(Vb.Net/3.5)

时间:2009-09-11 13:17:32

标签: vb.net visual-studio-2008 reflection assemblies

我想知道是否有人可以帮助我 - 我没有做太多的反思,但理解基本原则。

我正在尝试做什么:

我正在开发一个类,该类收集有关本地系统,网络等的大量信息,以用于自动错误报告。我不是每次添加新属性时都必须更改我的测试工具,而是(理想情况下)能够将该批次序列化为XML字符串并将其显示在文本框中。

不幸的是,框架不会在只读属性上使用默认的XML序列化程序(几乎所有的都是),因为它们不会正确反序列化

[不确定我同意任何序列化必须可反序列化的假设 - MS说这是“按设计”的功能,我想我可以理解 - 也许是一个标记,表明它应该被序列化无论如何会有利吗?]

最初的方法是使属性可以获取和设置(在setter上有抛出异常),但之后整理它的工作量似乎有点过分,我希望这些属性在最终版本中是只读的

我需要帮助:

我目前的计划是使用反射递归迭代我最顶层的聚类的每个(公共)属性。问题是,我见过的样本不会递归处理。另外,我只想检查一个对象的属性,如果它在我的一个程序集中 - 否则只需在它上面调用.ToString。

如果我没有将检查限制在我的程序集中,我假设我会得到一个字符串,然后包含一个长度,而该长度又会有.Tostring方法......

出于本项目的目的,我几乎保证我的代码中没有循环引用,因为这只会用作开发工具所以我不是担心它偶尔会肆无忌惮。

我很欣赏一些例子/建议。

非常感谢提前。

2 个答案:

答案 0 :(得分:3)

这有望让你入门。它将树直接打印到控制台,因此您需要调整为输出XML。然后更改IsMyOwnType方法以过滤掉您感兴趣的程序集,现在它只关心同一程序集中的类型。

Shared Sub RecurseProperties(o As Object, level As Integer)
    For Each pi As PropertyInfo In o.GetType().GetProperties()
        If pi.GetIndexParameters().Length > 0 Then Continue For

        Console.Write(New String(" "c, 2 * level))
        Console.Write(pi.Name)
        Console.Write(" = ")

        Dim propValue As Object = pi.GetValue(o, Nothing)
        If propValue Is Nothing Then
            Console.WriteLine("<null>")
        Else
            If IsMyOwnType(pi.PropertyType) Then
                Console.WriteLine("<object>")
                RecurseProperties(propValue, level+1)
            Else
                Console.WriteLine(propValue.ToString())
            End If
        End If

    Next
End Sub

Shared Function IsMyOwnType(t As Type) As Boolean
    Return t.Assembly Is Assembly.GetExecutingAssembly()
End Function

答案 1 :(得分:2)

c#上的扩展版本用于任何对象

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Extensions
{
    public static class ObjectExtension
    {
        public static string ToStringProperties(this object o)
        {
            return o.ToStringProperties(0);
        }
    public static string ToStringProperties(this object o, int level)
    {
        StringBuilder sb = new StringBuilder();
        string spacer = new String(' ', 2 * level);
        if (level == 0) sb.Append(o.ToString());
        sb.Append(spacer);
        sb.Append("{\r\n");
        foreach (PropertyInfo pi in o.GetType().GetProperties())
        {

            if (pi.GetIndexParameters().Length == 0)
            {
                sb.Append(spacer);
                sb.Append("  ");
                sb.Append(pi.Name);
                sb.Append(" = ");

                object propValue = pi.GetValue(o, null);
                if (propValue == null)
                {
                    sb.Append(" <null>");
                } else {
                    if (IsMyOwnType(pi.PropertyType))
                    {
                        sb.Append("\r\n");
                        sb.Append(((object)propValue).ToStringProperties(level + 1));
                    } else{
                        sb.Append(propValue.ToString());
                    }
                }
                sb.Append("\r\n");
            }
        }
        sb.Append(spacer);
        sb.Append("}\r\n");
        return sb.ToString();
    }
    private static bool IsMyOwnType(Type t) 
{
    return (t.Assembly == Assembly.GetExecutingAssembly());
}
}
}