Рефлексия — это получение информации о типах во время выполнения программы. Например, можно получить список всех классов и интерфейсов сборки, список элементов каждого из классов, список параметров каждого метода и т. д. Вся информация берется из метаданных сборки. Для использования рефлексии необходимы класс System.Type и типы пространства имен System.Reflection.
В классе Туре описаны методы, которые позволяют получить информацию о типах. В пространстве имен System.Reflection описаны типы, поддерживающие Туре, а также классы, которые служат для организации позднего связывания и динамической загрузки сборок. Наиболее важные свойства и методы класса Туре приведены в табл. 12.1.
Таблица 12.1. Элементы класса Туре
Элемент Описание
IsAbstract, IsArray, Свойства, позволяющие получить
IsNestedPublic, IsClass, соответствующие характеристики конкретного
IsNestedPrivate, IsCOMObject, типа в программе (например, является ли он
IsEnum, Islnterface, IsPrimitive, абстрактным, является ли он массивом,
IsSealed, IsValueType классом и т. п.). Приведены не все свойства
GetConstructors, GetEvents, Методы, возвращающие массив с набором
GetFields, GetInterfaces, соответствующих элементов (конструкторов,
GetMethods, GetMembers, событий, полей и т. п.). Возвращаемое значение
GetNestedTypes, GetProperties соответствует имени метода, например, GetFields
возвращает массив типа FieldInfo, GetMethods — массив типа MethodInfo. Для каждого из методов есть парный ему (без символа S в конце имени), который предназначен для работы с одним заданным в параметре элементом (например, GetMethod и GetMethods)
FindMembers Метод возвращает массив типа MemberInfo на основе заданных
критериев поиска
GetType Метод возвращает объект типа Туре по имени, заданному в виде
строки
InvokeMember Метод используется для позднего связывания заданного элемента
Воспользоваться этими методами можно после создания экземпляра класса Туре. Поскольку это абстрактный класс, обычный способ создания объектов с помощью операции new неприменим, зато существуют три других способа:
1. В базовом классе object описан метод GetType, которым можно воспользоваться для любого объекта, поскольку он наследуется. Метод возвращает объект
типа Туре, например:
Monster X = new Monster(); Type t = X.GetType();
2. В классе Type описан статический метод GetType с одним параметром строкового типа, на место которого требуется передать имя класса (типа), например:
Type t = Type.GetType("Monster");
3. Операция typeof возвращает объект класса Туре для типа, заданного в качестве параметра, например:
Type t = typeof(Monster);
При использовании второго и третьего способов создавать экземпляр исследуемого класса нет необходимости.
Как видно из табл. 12.1, многие методы класса Туре возвращают экземпляры стандартных классов (например, Member Info). Эти классы описаны в пространстве имен System.Reflection. Наиболее важные из этих классов перечислены в табл. 12.2.
Таблица 12.2. Некоторые классы пространства имен System.Reflection
Тип Описание
Assembly Содержит методы для получения информации о сборке, а также для загрузки
сборки и выполнения с ней различных операций
AssemblyName Позволяет получать информацию о сборке (имя, версия, совместимость,
естественный язык и т. п.)
EventInfo Хранит информацию о событии
FieldInfo Хранит информацию о поле
MemberInfo Абстрактный базовый класс, определяющий общие элементы для классов
EventInfo, FieldInfo, MethodInfo и PropertyInfo
MethodInfo Хранит информацию о методе
Module Позволяет обратиться к модулю в многофайловой сборке
ParameterInfo Хранит информацию о параметре
PropertyInfo Хранит информацию о свойстве
В листинге 12.3 приведены примеры использования рассмотренных методов и классов для получения информации о классах библиотеки из листинга 12.1.
Листинг 12.3.Получение информации о классах
using System;
using System.Reflection;
namespace ConsoleApplication1
{
using MonsterLib;
class Class1
{
static void Info(Type t)
{
Console.WriteLine("======= Класс " + t.FullName);
if (t.IsAbstract)
Console.WriteLine("абстрактный");
if (t.IsClass)
Console.WriteLine("обычный");
if (t.IsEnum)
Console.WriteLine("перечисление");
Console.WriteLine("базовый класс " + t.BaseType);
Methodlnfo[] met = t.GetMethods();
foreach (MethodInfo m in met)
Console.WriteLine(m);
Console.WriteLine();
PropertyInfo[] prs = t.GetProperties();
foreach (Propertylnfo p in prs)
Console.WriteLine(p);
Console.WriteLine();
}
static void Main()
{
Type t = typeof(Spirit);
Info(t);
t = typeof(Monster);
Info(t);
t = typeof(Daemon);
Info(t);
}
}
}
Результат работы программы:
======= класс MonsterLib.Spirit
абстрактный
обычный
базовый класс System.Object
Void Passport()
Int32 GetHashCode()
Boolean Equals(System.Object)
System.String ToString()
System.Type GetType()
======= класс MonsterLib.Monster
обычный
базовый класс MonsterLib.Spirit
Void Passport()
Int32 GetHashCode()
Boolean Equals(System.Object)
System.String ToString()
Int32 get_Health()
Void set_Health(Int32)
Int32 get_Ammo()
Void set_Ammo(Int32)
System.String get_Name()
System.Type GetType()
Int32 Health
Int32 Ammo
System.String Name
======= Класс MonsterLib.Daemon
обычный
базовый класс MonsterLib.Monster
Void Passport()
Int32 GetHashCode()
Boolean Equals(System.Object)
System.String ToString()
Void Think()
Int32 get_Health()
Void set_Health(Int32)
Int32 get_Ammo()
Void set_Ammo(Int32)
System.String get_Name()
System.Type GetType()
Int32 Health
Int32 Ammo
System.String Name
Можно продолжить исследования дальше, например, получить параметры и возвращаемое значение каждого метода. Думаю, что принцип вам уже ясен. Напомню, что вся эта информация берется из метаданных сборки.