Как я могу найти все общедоступные поля объекта в С#?

Я создаю метод, чтобы взять 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. Я исправлю это позже - прямо сейчас мне просто интересно, как получить все публичные поля, связанные с объектом.

РЕДАКТИРОВАТЬ: Извините за ответы flip-flopping. Я должен был попробовать каждый метод, прежде чем выбирать ответ.

Ответ 1

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: -)

Ответ 2

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

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

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

GetFields(BindingFlags.Public | BindingFlags.Instance)

Ответ 3

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, представляющих все общедоступные поля, определенные для текущего типа.

Ответ 4

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

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

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

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

Ответ 5

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