Как я могу найти все открытые поля объекта в C #?
Вопрос
Я создаю метод, который принимает 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. Я исправлю это позже - сейчас мне просто интересно, как получить все открытые поля, связанные с объектом.
Решение
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; -)
Другие советы
Вы можете получить все поля объекта, объявленные непосредственно в классе, с помощью BindingFlags:
GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
и все поля объекта, включая унаследованные с:
GetFields(BindingFlags.Public | BindingFlags.Instance)
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, представляющих все открытые поля , определенные для текущего типа.
Конечно, другой вопрос: "Почему у вас есть открытые поля?" - свойства являются предпочтительными. В качестве абстракции обратите внимание, что рефлексия - не единственный вариант: для типа также возможно, чтобы его свойства отображались на лету во время выполнения (например, как нетипизированный DataTable
/ DataView
предоставляет столбцы как свойства).
Для поддержки этого (также поддерживая простые объекты), вы должны использовать TypeDescriptor
:
foreach(PropertyDescriptor prop in TypeDescriptor.GetProperties(obj))
{
Console.WriteLine("{0}={1}", prop.Name, prop.GetValue(obj));
}
Это также допускает многочисленные варианты расширяемости, например, значительно ускорение отражения (без изменения кода).
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());
}
}
}