Книга: ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Генерирование динамического компоновочного блока

Генерирование динамического компоновочного блока

Чтобы проиллюстрировать процесс определения компоновочного блока .NET в среде выполнения, давайте создадим одномодульный динамический компоновочный блок с именем MyAssembly.dll. В этом модуле будет содержаться класс HelloWorld. Тип HelloWorld поддерживает конструктор, используемый по умолчанию, и пользовательский конструктор для присваивания значения приватной переменной (theMessage) типа string. Кроме того, HelloWorld предлагает открытый метод экземпляра с именем SayHello(), который выводит приветствие в стандартный поток ввода-вывода, а также еще один метод экземпляра, GetMsg(), который возвращает внутреннюю приватную строку. В результате вы должны программно сгенерировать следующий тип класса.

// Этот класс будет создан в среде выполнения
// с помощью System.Reflection.Emit.
public class HelloWorld {
 private string theMessage;
 HelloWorld() {}
 HelloWorld(string s) { theMessage = s; }
 public string GetMsg() { return theMessage; }
 public void SayHello() {
  System.Console.WriteLine("Привет от класса HelloWorld!");
 }
}

Предположим, вы cоздали новый проект консольного приложения в Visual Studio 2005, назвав его DynAsmBuilder. Переименуйте исходный класс в MyAsmBuilder и определите статический метод с именем CreateMyAsm(). Этот единственный метод будет ответственен за следующее:

• определение характеристик динамического компоновочного блока (имя, версия и т.д.);

• реализацию тина HelloClass;

• запись компоновочного блока, сгенерированного в памяти, в физический файл.

Также отметим, что метод CreateMyAsm() использует в качестве единственного параметра тип System.AppDomain, который будет использоваться для получения доступа к типу AssemblyBuilder, связанному с текущим доменом приложения (см. главу 13, где обсуждаются домены приложений .NET). Вот полный программный код, с последующим анализом.

// Вызывающая сторона посылает тип AppDomain.
public static void CreateMyAsm(AppDomain currAppDomain) {
 // Установка общих характеристик компоновочного блока.
 AssemblyName assemblyName = new AssemblyName();
 assemblyName.Name = "MyAssembly";
 assemblyName.Version = new Version("1.0.0.0");
 // Создание нового компоновочного блока
 // в рамках текущего домена приложения.
 AssemblyBuilder assembly = curAppDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save);
 // Поскольку создается одномодульный компоновочный блок,
 // имя модуля будет совпадать с именем компоновочного блока.
 ModuleBuilder module = assembly.DefineDynamicModule("MyAssembly", "MyAssemblу.dll");
 // Определение открытого класса с именем "HelloWorld".
 TypeBuilder helloWorldClass = module.DefineType("MyAssembly.HelloWorld", TypeAttributes.Public);
 // Определение приватной переменной String с именем "theMessage".
 FieldBuilder msgField = helloWorldClass.DefineField("theMessage", Type.GetType("System.String"), FieldAttributes.Private);
 // Создание пользовательского конструктора.
 Type[] constructorArgs = new Type[1];
 constructorArgs[0] = typeof(string);
 ConstructorBuilder constructor = helloWorldClass.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, constructorArgs);
 ILGenerator constructorIL = constructor.GetILGenerator();
 constructorIL.Emit(OpCodes.Ldarg_0);
 Type objectClass = typeof(object);
 ConstructorInfo superConstructor = objectClass.GetConstructor(new Type[0]);
 constructorIL.Emit(OpCodes.Call, superConstructor);
 constructorIL.Emit(Opcodes.Ldarg_0);
 constructorIL.Emit(Opcodes.Ldarg_1);
 constructorIL.Emit(OpCodes.Stfld, msgField);
 constructorIL.Emit(OpCodes.Ret);
 // Создание конструктора, заданного по умолчанию.
 helloWorldClass.DefineDefaultConstructor(MethodAttributes.Public);
 // Теперь создание метода GetMsg().
 MethodBuilder getMsgMethod = helloWorldClass.DefineMethod("GetMsg", MethodAttributes.Public, typeof(string), null);
 ILGenerator methodIL = getMsgMethod.GetILGenerator();
 methodIL.Emit(OpCodes.Ldarg_0);
 methodIL.Emit(OpCodes.Ldfld, msgField);
 methodIL.Emit(Opcodes.Ret);
 // Создание метода SayHello.
 MethodBuilder sayHiMethod = helloWorldClass.DefineMethod("SayHello", MethodAttributes.Public, null, null);
 methodIL = sayHiMethod.GetILGenerator();
 methodIL.EmitWriteLine("Привет от класса HelloWorld!");
 methodIL.Emit(Opcodes.Ret);
 // Генерирование класса HelloWorld.
 helloWorldClass.CreateType();
 // (Необязательно.) Сохранение компоновочного блока в файл.
 assembly.Save("MyAssembly.dll");
}

Оглавление книги


Генерация: 1.155. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз