Common Intermediate Language и системное программирование в Microsoft.Net. Макаров А.В - 85 стр.

UptoLike

3. И, наконец, если нам надо загрузить внешнюю сборку, мы ис-
пользуем статический метод LoadFrom:
Assembly assembly = Assembly.LoadFrom(“test.exe”).
Сборка .NET, как правило, состоит из одного модуля, хотя существу-
ет возможность включения в сборку сразу нескольких модулей. Получе-
ние доступа к объектам класса Module, описывающим модули, из которых
состоит сборка, осуществляется одним из двух способов:
1. Если мы знаем имя модуля, то мы можем использовать метод
GetModule класса Assembly:
Module module = assembly.GetModule(“SomeModule.exe”).
2. Кроме того, мы можем вызвать метод GetModules для получения
массива объектов класса Module, соответствующих всем модулям
в сборке:
Module[] modules = assembly.GetModules(false).
Через объект класса Module мы можем обратиться к глобальным по-
лям и функциям модуля (глобальные поля и функции не принадлежат ни
одному классу), используя методы GetField и GetFields для полей, а также
GetMethod и GetMethods для функций. При этом полям будут соответство-
вать объекты класса FieldInfo, а методам – объекты класса MethodInfo. В
следующем примере мы выводим на экран сигнатуры всех глобальных
функций некоторой сборки «test.exe»:
Assembly assembly = Assembly.LoadFrom(“test.exe”);
Module[] modules = assembly.GetModules(false);
Анализ кода на CIL
157
Генерация метаданных осуществляется через методы интерфейса
IMetadataEmit, которые можно условно разделить на две группы:
1. Методы DefineXXX добавляют новые элементы метаданных;
2. Методы SetXXX устанавливают свойства элементов метаданных.
Сгенерированные метаданные могут быть сохранены на диске при
помощи метода Save.
4.4.2. Reflection API
Библиотека рефлексии содержит классы для работы с метаданными
на высоком уровне (эти классы располагаются в пространствах имен
System.Reflection и System.Reflection.Emit). Она соответствует специфи-
кации CLS, поэтому использующий ее метаинструмент может быть напи-
сан на любом языке платформы .NET, который является потребителем
CLS-библиотек.
4.4.2.1. Чтение метаданных через рефлексию
Метаинструмент, использующий библиотеку рефлексии, получает дос-
туп к метаданным сборки через экземпляр класса Assembly, который создает-
ся при загрузке сборки в память. Затем через методы класса Assembly можно
получить объекты класса Module, которые соответствуют модулям, входящим
в сборку. Класс Module, в свою очередь, позволяет получить набор экземпля-
ров класса Type для входящих в модуль типов, а уже через эти объекты мож-
но добраться до конструкторов (класс ConstructorInfo), методов (класс
MethodInfo) и полей (класс FieldInfo) типов. То есть библиотека рефлексии
спроектирована таким образом, что создание объектов рефлексии, соответ-
ствующих элементам метаданных, осуществляется путем вызова методов
других объектов рефлексии (схема получения доступа к объектам рефлексии
показана на рис. 4.5, при этом сплошные стрелки обозначают основные пу-
ти получения доступа, а пунктирные – дополнительные пути). Другими сло-
вами, конструкторы классов, входящих в библиотеку, для пользователя биб-
лиотеки недоступны. Информацию о любом элементе метаданных можно
прочитать из свойств соответствующего ему объекта рефлексии.
Экземпляр класса Assembly, с создания которого, как правило, начинает-
ся работа со сборкой через рефлексию, можно получить разными способами:
1. Если нас интересует текущая работающая сборка, мы можем
вызвать статический метод GetExecutingAssembly класса
Assembly:
Assembly assembly = Assembly.GetExecutingAssembly().
2. Если мы хотим получить доступ к сборке, в которой объявлен
некоторый тип данных, мы можем воспользоваться статическим
методом GetAssembly:
Assembly assembly = Assembly.GetAssembly(typeof(int)).
156
CIL и системное программирование в Microsoft .NET
Assembly
Module
Type
FieldInfo
MethodInfo
ConstructorInfo
PropertyInfo
ParameterInfo
Рис. 4.5. Получение доступа к объектам рефлексии
156                          CIL и системное программирование в Microsoft .NET   Анализ кода на CIL                                                    157


     Генерация метаданных осуществляется через методы интерфейса
IMetadataEmit, которые можно условно разделить на две группы:                                 Assembly                   FieldInfo
       1. Методы DefineXXX добавляют новые элементы метаданных;
       2. Методы SetXXX устанавливают свойства элементов метаданных.
     Сгенерированные метаданные могут быть сохранены на диске при                                 Module                MethodInfo         ParameterInfo
помощи метода Save.
4.4.2. Reflection API
                                                                                                         Type         ConstructorInfo
     Библиотека рефлексии содержит классы для работы с метаданными
на высоком уровне (эти классы располагаются в пространствах имен
System.Reflection и System.Reflection.Emit). Она соответствует специфи-
                                                                                                                       PropertyInfo
кации CLS, поэтому использующий ее метаинструмент может быть напи-
сан на любом языке платформы .NET, который является потребителем
CLS-библиотек.
                                                                                      Рис. 4.5. Получение доступа к объектам рефлексии
4.4.2.1. Чтение метаданных через рефлексию
      Метаинструмент, использующий библиотеку рефлексии, получает дос-                  3. И, наконец, если нам надо загрузить внешнюю сборку, мы ис-
туп к метаданным сборки через экземпляр класса Assembly, который создает-                  пользуем статический метод LoadFrom:
ся при загрузке сборки в память. Затем через методы класса Assembly можно                     Assembly assembly = Assembly.LoadFrom(“test.exe”).
получить объекты класса Module, которые соответствуют модулям, входящим               Сборка .NET, как правило, состоит из одного модуля, хотя существу-
в сборку. Класс Module, в свою очередь, позволяет получить набор экземпля-       ет возможность включения в сборку сразу нескольких модулей. Получе-
ров класса Type для входящих в модуль типов, а уже через эти объекты мож-        ние доступа к объектам класса Module, описывающим модули, из которых
но добраться до конструкторов (класс ConstructorInfo), методов (класс            состоит сборка, осуществляется одним из двух способов:
MethodInfo) и полей (класс FieldInfo) типов. То есть библиотека рефлексии               1. Если мы знаем имя модуля, то мы можем использовать метод
спроектирована таким образом, что создание объектов рефлексии, соответ-                    GetModule класса Assembly:
ствующих элементам метаданных, осуществляется путем вызова методов                            Module module = assembly.GetModule(“SomeModule.exe”).
других объектов рефлексии (схема получения доступа к объектам рефлексии                 2. Кроме того, мы можем вызвать метод GetModules для получения
показана на рис. 4.5, при этом сплошные стрелки обозначают основные пу-                    массива объектов класса Module, соответствующих всем модулям
ти получения доступа, а пунктирные – дополнительные пути). Другими сло-                    в сборке:
вами, конструкторы классов, входящих в библиотеку, для пользователя биб-                      Module[] modules = assembly.GetModules(false).
лиотеки недоступны. Информацию о любом элементе метаданных можно                      Через объект класса Module мы можем обратиться к глобальным по-
прочитать из свойств соответствующего ему объекта рефлексии.                     лям и функциям модуля (глобальные поля и функции не принадлежат ни
      Экземпляр класса Assembly, с создания которого, как правило, начинает-     одному классу), используя методы GetField и GetFields для полей, а также
ся работа со сборкой через рефлексию, можно получить разными способами:          GetMethod и GetMethods для функций. При этом полям будут соответство-
         1. Если нас интересует текущая работающая сборка, мы можем              вать объекты класса FieldInfo, а методам – объекты класса MethodInfo. В
            вызвать статический метод GetExecutingAssembly класса                следующем примере мы выводим на экран сигнатуры всех глобальных
            Assembly:                                                            функций некоторой сборки «test.exe»:
              Assembly assembly = Assembly.GetExecutingAssembly().
         2. Если мы хотим получить доступ к сборке, в которой объявлен                Assembly assembly = Assembly.LoadFrom(“test.exe”);
            некоторый тип данных, мы можем воспользоваться статическим                Module[] modules = assembly.GetModules(false);
            методом GetAssembly:
              Assembly assembly = Assembly.GetAssembly(typeof(int)).