Отражение - рекурсивно повторяйте свойства объекта в моих сборках - PullRequest
0 голосов
/ 11 сентября 2009

Интересно, сможет ли кто-нибудь мне помочь - я не особо задумался, но понимаю основные принципы.

Что я пытаюсь сделать:

Я нахожусь в процессе разработки класса, который собирает много информации о локальной системе, сети и т. Д. ... для использования в автоматических отчетах об ошибках. Вместо того, чтобы менять свой тестовый комплект каждый раз, когда я добавляю новое свойство, я (в идеале) хотел бы иметь возможность сериализовать лот в виде строки XML и просто отобразить его в текстовом поле.

К сожалению, Framework не будет использовать сериализатор XML по умолчанию для свойств только для чтения (которые почти все мои), поскольку они не будут десериализованы должным образом

[ Не уверен, что я согласен с предположением, что все сериализованное должно быть десериализуемым - MS говорит, что это особенность «по замыслу», которую, я полагаю, я могу понять - Возможно, это тег, указывающий, что оно должно быть сериализовано в любом случае было бы выгодно? ]

Первоначальный подход состоял в том, чтобы сделать свойства доступными для установки и установки (за исключением исключения броска в установщике), но объем работ по приведению в порядок этого впоследствии кажется немного чрезмерным, и я хотел бы, чтобы свойства были доступны только для чтения в окончательной версии .

В чем мне нужна помощь:

Мой текущий план - использовать рефлексию для рекурсивной итерации каждого (открытого) свойства моего высшего класса сбора. Проблема в том, что образцы, которые я видел, не обрабатывают вещи рекурсивно. Кроме того, я хочу проверять свойства объекта только в том случае, если он находится в одной из моих сборок - в противном случае просто вызовите .ToString для него.

Если у меня нет проверки, ограниченной моей сборкой, я предполагаю, что получу (скажем) строку, которая затем содержит длину, которая в свою очередь будет иметь метод .Tostring ...

Для целей этого проекта я могу почти гарантировать отсутствие циклических ссылок в моем коде, и это будет использоваться только как инструмент разработки, так что я не слишком заинтересован о том, что это время от времени выходит из-под контроля.

Буду признателен за некоторые примеры / советы.

Заранее большое спасибо.

Ответы [ 2 ]

3 голосов
/ 14 сентября 2009

Надеюсь, это поможет вам начать. Он выводит дерево непосредственно на консоль, поэтому вам нужно будет настроить вывод 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
2 голосов
/ 28 февраля 2011

версия вашего расширения на 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());
}
}
}
...