Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.docx
Скачиваний:
13
Добавлен:
03.11.2018
Размер:
614.46 Кб
Скачать

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<int>); // сконструированный тип

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

}