2.22. МЕТАДАННЫЕ И ПОЛУЧЕНИЕ ИНФОРМАЦИИ О ТИПАХ
При создании сборки в неё помещаются метаданные, которые являются описанием всех типов в сборке и их элементов. Программист может работать с метаданными, используя специальный механизм, называемый отражением (reflection). Главные элементы, которые необходимы для использования возможностей отражения – это класс System.Type и типы из пространств имён System.Reflection и System.Reflection.Emit.
Класс System.Type служит для получения информации о типе. Существует несколько способов получить объект этого класса:
1. Вызвать у объекта метод GetType(). Данный метод определен на уровне System.Object, а значит, присутствует у любого объекта:
Foo foo = new Foo(); // Foo – это некий класс
Type t = foo.GetType();
2. Использовать статический метод Type.GetType(), которому передается имя типа в виде строки (имя должно быть полным, то есть включать пространство имён):
Type t = Type.GetType("Foo");
3. Использовать операцию C# typeof, параметром которой является тип:
Type t = typeof(Foo);
Операцию typeof можно применять к массивам и универсальным шаблонам. Причём в последнем случае допускается использовать как конструируемый тип, так и исходный тип-шаблон (обратите внимание на синтаксис записи универсального шаблона).
Type t1 = typeof(int[]);
Type t2 = typeof(char[,]);
Type t3 = typeof(List); // сконструированный тип
Type t4 = typeof(List<>); // универсальный тип
Свойства класса Type позволяют узнать имя типа, имя базового типа, является ли тип универсальным, в какой сборке он размещается и другую информацию. Кроме этого, Type имеет специальные методы, возвращающие данные о полях типа, свойствах, событиях, методах и их параметрах.
Рассмотрим пример получения информации о типе. Будем анализировать примитивный тип System.Int32:
Type t = typeof(Int32);
Console.WriteLine("Full name = " + t.FullName);
Console.WriteLine("Base is = " + t.BaseType);
Console.WriteLine("Is sealed = " + t.IsSealed);
Console.WriteLine("Is class = " + t.IsClass);
foreach (FieldInfo f in t.GetFields())
{
Console.WriteLine("Field = " + f.Name);
}
foreach (PropertyInfo p in t.GetProperties())
{
Console.WriteLine("Property = " + p.Name);
}
foreach (MethodInfo m in t.GetMethods())
{
Console.WriteLine("Method Name = " + m.Name);
Console.WriteLine("Method Return Type = " + m.ReturnType);
foreach (ParameterInfo pr in m.GetParameters())
{
Console.WriteLine("Parameter Name = " + pr.Name);
Console.WriteLine("Type = " + pr.ParameterType);
}
}
Как показывает пример, информация об элементах типа хранится в объектах специальных классов FieldInfo, PropertyInfo, MethodInfo и т. п. Эти классы находятся в пространстве имён System.Reflection. Кроме этого, код примера покажет данные только об открытых элементах типа. Составом получаемой информации можно управлять, передавая в Get-методы дополнительные флаги перечисления System.Reflection.BindingFlags (табл. 16).
Таблица 16
Флаги BindingFlags, связанные с получением информации о типе
Флаг
|
Описание
|
Default
|
Отсутствие специальных флагов
|
IgnoreCase
|
Игнорировать регистр имён получаемых элементов
|
DeclaredOnly
|
Получить элементы, объявленные непосредственно в типе (игнорировать унаследованные элементы)
|
Instance
|
Получить экземплярные элементы
|
Static
|
Получить статические элементы
|
Public
|
Получить открытые элементы
|
NonPublic
|
Получить закрытые элементы
|
FlattenHierarchy
|
Получить public и protected элементы у типа и у всех его предков
|
var bf = BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Static | BindingFlags.Instance;
FieldInfo[] fi = t.GetFields(bf);
Пространство имен System.Reflection содержит типы для получения информации и манипулирования сборкой и модулем сборки. При помощи класса Assembly можно получить информацию о сборке, при помощи класса Module о модуле. Основные элементы данных классов перечислены в табл. 17 и табл. 18.
Таблица 17
Основные элементы класса Assembly
Имя элемента
|
Описание
|
CreateInstance()
|
Находит по имени тип в сборке и создает его экземпляр
|
FullName
|
Строковое свойство с полным именем сборки
|
GetAssembly()
|
Ищет в памяти и возвращает объект Assembly, который содержит указанный тип (статический метод)
|
GetCustomAttributes()
|
Получает атрибуты сборки
|
GetExecutingAssembly()
|
Возвращает сборку, которая содержит выполняемый в текущий момент код (статический метод)
|
GetExportedTypes()
|
Возвращает public-типы, определенные в сборке
|
GetFiles()
|
Возвращает файлы, из которых состоит сборка
|
GetLoadedModules()
|
Возвращает все загруженные в память модули сборки
|
GetModule()
|
Получает указанный модуль сборки
|
GetModules()
|
Возвращает все модули, являющиеся частью сборки
|
GetName()
|
Возвращает объект AssemblyName для сборки
|
GetReferenced-Assemblies()
|
Возвращает объекты AssemblyName для всех сборок, на которые ссылается данная сборка
|
GetTypes()
|
Возвращает типы, определенные в сборке
|
Load()
|
Статический метод, который загружает сборку по имени
|
LoadFrom()
|
Статический метод; загружает сборку из указанного файла
|
LoadModule()
|
Загружает внутренний модуль сборки в память
|
Таблица 18
Основные элементы класса Module
Имя элемента
|
Описание
|
Assembly
|
Свойство с указанием на сборку (объект Assembly) модуля
|
FindTypes()
|
Получает массив классов, удовлетворяющих заданному фильтру
|
FullyQualifiedName
|
Строка, содержащая полное имя и путь к модулю
|
GetType()
|
Пытается выполнить поиск указанного типа в модуле
|
GetTypes()
|
Возвращает все типы, определенные в модуле
|
Name
|
Строка с коротким именем модуля
|
Продемонстрируем пример работы с классами Assembly и Module:
var assembly = Assembly.GetExecutingAssembly();
Console.WriteLine(assembly.FullName);
foreach (Module module in assembly.GetModules())
{
Console.WriteLine(module.FullyQualifiedName);
foreach (Type type in module.GetTypes())
Console.WriteLine(type.FullName);
}
Поделитесь с Вашими друзьями: |