Как я могу найти все открытые поля объекта в C #? - PullRequest
14 голосов
/ 26 октября 2008

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

В настоящее время мой код выглядит следующим образом:

public static void ListArrayListMembers(ArrayList list)
    {
        foreach (Object obj in list)
        {
            Type type = obj.GetType();
            string field = type.GetFields().ToString();
            Console.WriteLine(field);

        }
    }

Конечно, я понимаю непосредственную проблему с этим кодом: если бы он работал, он напечатал бы только одно поле на объект в ArrayList. Я исправлю это позже - сейчас мне просто интересно, как получить все открытые поля, связанные с объектом.

Ответы [ 5 ]

26 голосов
/ 26 октября 2008
foreach (Object obj in list) {
    Type type = obj.GetType();

    foreach (var f in type.GetFields().Where(f => f.IsPublic)) {
        Console.WriteLine(
            String.Format("Name: {0} Value: {1}", f.Name, f.GetValue(obj));
    }                           
}

Обратите внимание, что для работы этого кода требуется .NET 3.5; -)

7 голосов
/ 26 октября 2008

Вы можете получить все поля объекта, объявленные непосредственно в классе, с помощью BindingFlags:

GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)

и все поля объекта, включая унаследованные с:

GetFields(BindingFlags.Public | BindingFlags.Instance)
4 голосов
/ 26 октября 2008
public static void ListArrayListMembers(ArrayList list)
{
    foreach (Object obj in list)
    {
        Type type = obj.GetType();
        Console.WriteLine("{0} -- ", type.Name);
        Console.WriteLine(" Properties: ");
        foreach (PropertyInfo prop in type.GetProperties())
        {
            Console.WriteLine("\t{0} {1} = {2}", prop.PropertyType.Name, 
                prop.Name, prop.GetValue(obj, null));
        }
        Console.WriteLine(" Fields: ");
        foreach (FieldInfo field in type.GetFields())
        {
            Console.WriteLine("\t{0} {1} = {2}", field.FieldType.Name, 
                field.Name, field.GetValue(obj));
        }
    }
}

Я хотел бы отметить, что поиск IsPublic в полях необязателен, так как type.GetFields (), как определено MSDN , сообщает:

Возвращаемое значение - Тип: System.Reflection.FieldInfo []

Массив объектов FieldInfo, представляющих все открытые поля , определенные для текущего Типа.

3 голосов
/ 26 октября 2008

Конечно, другой вопрос будет: «Почему у вас есть публичные поля?» - свойства являются предпочтительными. В качестве абстракции обратите внимание, что отражение - не единственный вариант: для типа также возможно, чтобы его свойства отображались на лету во время выполнения (например, как нетипизированный DataTable / DataView представляет столбцы как свойства).

Для поддержки этого (также поддерживая простые объекты), вы должны использовать TypeDescriptor:

        foreach(PropertyDescriptor prop in TypeDescriptor.GetProperties(obj))
        {
            Console.WriteLine("{0}={1}", prop.Name, prop.GetValue(obj));
        }

Это также допускает многочисленные возможности расширения - например, значительно ускорение отражения (без изменения какого-либо кода).

1 голос
/ 26 октября 2008
    static void ListArrayListMembers(ArrayList list)
    {
        foreach (object obj in list)
        {
            Type type = obj.GetType();
            foreach (FieldInfo field in type.GetFields(BindingFlags.Public))
            {
                Console.WriteLine(field.Name + " = " + field.GetValue(obj).ToString());
            }
        }
    }
...