ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
Шрифт:
Таблица 15.8. Избранные члены пространства имен System.Reflection.Emit
Члены | Описание |
---|---|
AssemblyBuilder | Используется для создания компоновочного блока (*.dll или *.exe) в среде выполнения. В случае *.exe следует вызвать метод ModuleBuilder.SetEntryPoint, чтобы указать метод, являющийся точкой входа в модуль. Если точка входа не указана, будет сгенерирована *.dll |
ModuleBuilder | Используется для определения множества модулей в рамках данного компоновочного блока |
EnumBuilder | Используется для создания типа перечня .NET |
TypeBuilder | Может
|
MethodBuilder EventBuilder LocalBuilder PropertyBuilder FieldBuilder ConstructorBuilder CustomAttributeBuilder ParameterBuilder | Используются для создания членов типа (таких как методы, локальные переменные, свойства, конструкторы и атрибуты) в среде выполнения |
ILGenerator | Генерирует коды операций CIL в данном члене типа |
OpCodes | Обеспечивает множество полей, отображающихся в коды операций CIL. Этот тип используется вместе с различными членами System.Reflection.Emit.ILGenerator |
В общем, типы пространства имен System.Reflection.Emit при построении динамического двоичного модуля позволяют представлять "сырые" лексемы CIL программными единицами. Возможности использования многих из указанных членов будут продемонстрированы в следующем примере, но тип ILGenerator заслуживает отдельного обсуждения.
Роль System.Reflection.Emit.ILGenerator
Как следует из самого имени указанного типа, роль ILGenerator заключается в добавлении кодов операций CIL в данный член типа. Обычно нет необходимости непосредственно создавать объект ILGenerator, а нужно просто получить действительную ссылку на тип ILGenerator, используя типы, связанные с компоновщиком (такие как MethodBuilder и ConstructorBuilder). Например:
Имея ILGenerator, вы можете генерировать "сырые" коды операций CIL, используя любые из целого набора методов. Некоторые (но, конечно же, не все) методы ILGenerator описаны в табл. 15.9.
Таблица 15.9. Подборка методов ILGenerator
Метод | Описание |
---|---|
BeginCatchBlock | Начинает блок catch |
BeginExceptionBlock | Начинает блок неотфильтрованного исключения |
BeginFinallyBlock | Начинает блок finally |
BeginScope | Начинает лексический контекст |
DeclareLocal | Объявляет локальную переменную |
DefineLabel | Объявляет новую метку |
Emit | Является перегруженным и позволяет генерировать коды операций CIL |
EmitCall | Вставляет код операции call или callvirt в поток CIL |
EmitWriteLine | Генерирует вызов Console.WriteLine с различными типами значений |
EndExceptionBlock | Завершает блок исключения |
EndScope | Завершает лексический контекст |
ThrowException | Создает инструкцию для генерирования исключения |
UsingNamespace | Указывает пространство имен, которое будет использоваться для оценки локальных переменных и наблюдаемых значений в текущем активном лексическом контексте |
Ключевым методом ILGenerator является метод Emit, который работает в совокупности с типом класса System.Reflection.Emit.OpCodes. Как уже упоминалось в этой главе, данный тип открывает большой набор доступных только для чтения полей, отображающихся в коды операций CIL. Полностью эти члены описаны в оперативно доступной системе справки, но целый ряд примеров вы сможете увидеть и на следующих страницах.
Генерирование динамического компоновочного блока
Чтобы проиллюстрировать процесс определения компоновочного блока .NET в среде выполнения, давайте создадим одномодульный динамический компоновочный блок с именем MyAssembly.dll. В этом модуле будет содержаться класс HelloWorld. Тип HelloWorld поддерживает конструктор, используемый по умолчанию, и пользовательский конструктор для присваивания значения приватной переменной (theMessage) типа string. Кроме того, HelloWorld предлагает открытый метод экземпляра с именем SayHello, который выводит приветствие в стандартный поток ввода-вывода, а также еще один метод экземпляра, GetMsg, который возвращает внутреннюю приватную строку. В результате вы должны программно сгенерировать следующий тип класса.
Предположим, вы cоздали новый проект консольного приложения в Visual Studio 2005, назвав его DynAsmBuilder. Переименуйте исходный класс в MyAsmBuilder и определите статический метод с именем CreateMyAsm. Этот единственный метод будет ответственен за следующее:
• определение характеристик динамического компоновочного блока (имя, версия и т.д.);
• реализацию тина HelloClass;
• запись компоновочного блока, сгенерированного в памяти, в физический файл.
Также отметим, что метод CreateMyAsm использует в качестве единственного параметра тип System.AppDomain, который будет использоваться для получения доступа к типу AssemblyBuilder, связанному с текущим доменом приложения (см. главу 13, где обсуждаются домены приложений .NET). Вот полный программный код, с последующим анализом.