Метаданные и отражение
Пример Serialization (Сериализация) из главы 2 "Основы технологии .NET" демонстрирует, как благодаря метаданным общеязыковая среда времени выполнения CLR поддерживает работу сервисов. Многие из технологий, которые мы рассматриваем в других главах книги, основаны на метаданных, хотя мы не всегда будем акцентировать на этом внимание.
Метаданные – это информация о сборках, модулях и типах, составляющих программы в .NET. Тот, кому когда-либо приходилось создавать язык описания интерфейса (IDL) с целью сгенерировать библиотеку типов так, чтобы созданные с помощью C++ СОМ-объекты могли вызываться из Visual Basic, или создавать заместители и заглушки, оценит, насколько полезными являются метаданные, и будет благодарен, что распространяется это все "бесплатно".
Компиляторы генерируют метаданные, а общеязыковая среда времени выполнения CLR, каркас .NET Framework и наши собственные программы могут их использовать. Чтобы лучше разобраться в том, как работают метаданные, мы сосредоточимся на обсуждении их использования, а не на их создании. Метаданные можно прочитать с помо-. шью классов из пространства имен System::Reflection (Система::Отражение).
Когда загружаются сборка и связанные с ней модули и типы, метаданные подгружаются вместе с ними. Затем можно сделать запрос к сборке, чтобы получить связанные с ней типы. Можно также вызвать метод GetType для любого из типов общеязыковой среды времени выполнения CLR и получить его метаданные. GetType – это метод класса System::Object (Система::Объект), производным от которого является каждый тип общеязыковой среды времени выполнения CLR. После того, как получен Type (Тип), связанный с объектом, можно использовать методы отражения, чтобы получить соответствующие метаданные.
Программа-пример Reflection (Отражение) берет изучаемую сборку Customer (Клиент) и распечатывает некоторые из доступных метаданных. В следующих разделах книги вы изучите распечатку и исходный код. Особенно важно сравнить вывод программы с исходным кодом в файле customer.h.
Программа ясно показывает, что из сборки можно извлечь все типы и восстановить структуры, интерфейсы, свойства, события и методы, связанные с этими типами. Сначала мы загружаем сборку в память и выводим ее имя.
Assembly *a = Assembly::Load(assemblyName); // Загрузка Console::WriteLine ( "Assembly {0} found.", a › FullName);
Вывод для этого оператора соответствует неподписанной сборке:
Assembly Customer, Version=1.0.643.18973, Culture=neutral, PublicKeyToken=null found.
CodeBase – одно из свойств класса Assembly; оно обсуждалось в главе 7 "Сборки и развертывание". Подтверждение защиты, связанное с этой сборкой, – это еще одно свойство. Следующий код пробует определить точку входа сборки:
Methodlnfo *entryMethodInfo = a › EntryPoint;
Так как это типичный написанный на C++ компонент сборки, то его точка входа – _DllMainCRTStartup@12. Если бы он был исполняемой программой, мы могли бы использовать метод Invoke (Вызвать) класса Methodlnfo, чтобы выполнить код инициализации сборки.
В данном примере для поиска связанных с этой сборкой модулей используется метод GetModules сборки. В данном случае мы имеем только один модуль, customer.dll. Затем мы могли бы найти типы, связанные с этим модулем. Вместо этого мы используем метод GetTypes сборки, чтобы возвратить массив типов сборки.