Язык программирования C#9 и платформа .NET5
Часть 357 из 642 Информация о книге
ConstructorBuilder myCtorBuilder = /* */;ILGenerator myCILGen = myCtorBuilder.GetILGenerator();Имея объект
, с помощью его методов можно выпускать низкоуровневые коды операций CIL. Некоторые (но не все) методыILGeneratorкратко описаны в табл. 19.8.ILGeneratorОсновным методом класса
являетсяILGenerator, который работает в сочетании с типомEmit(). Как упоминалось ранее в главе, данный тип открывает доступ к множеству полей только для чтения, которые отображаются на низкоуровневые коды операций CIL. Полный набор этих членов документирован в онлайновой справочной системе, и далее в главе вы неоднократно встретите примеры их использования.System.Reflection.Emit.OpcodesВыпуск динамической сборки
Чтобы проиллюстрировать процесс определения сборки .NET Core во время выполнения, давайте рассмотрим процесс создания однофайловой динамической сборки по имени
.MyAssembly.dllВнутри модуля находится класс
, который поддерживает стандартный конструктор и специальный конструктор, применяемый для присваивания значения закрытой переменной-члена (HelloWorld) типаtheMessage. Вдобавок в классеstringимеется открытый метод экземпляра под названиемHelloWorld, который выводит приветственное сообщение в стандартный поток ввода-вывода, и еще один метод экземпляра по имениSayНеllo(), возвращающий внутреннюю закрытую строку. По существу мы собираемся программно сгенерировать следующий тип класса:GetMsg()<b>// Этот класс будет создаваться во время выполнения с использованием</b><b>// пространства имен System.Reflection.Emit.</b>public class HelloWorld{private string theMessage;HelloWorld() {}HelloWorld(string s) {theMessage = s;}public string GetMsg() {return theMessage;}public void SayHello(){System.Console.WriteLine("Hello from the HelloWorld class!");}}Создайте новый проект консольного приложения по имени
и добавьте NuGet-пакетMyAsmBuilder. Импортируйте в него пространства именSystem.Reflection.EmitиSystem.Reflection. Определите в классеSystem.Reflection.Emitстатический метод по имениProgram. Этот единственный метод будет отвечать за решение следующих задач:CreateMyAsm()• определение характеристик динамической сборки (имя, версия и т.п.);
• реализация типа
;HelloClass• возвращение вызывающему методу объекта
.AssemblyBuilderНиже приведен полный код, а затем его анализ:
static AssemblyBuilder CreateMyAsm(){<b> // Установить общие характеристики сборки.</b>AssemblyName assemblyName = new AssemblyName{Name = "MyAssembly",Version = new Version("1.0.0.0")};<b> // Создать новую сборку.</b>var builder = AssemblyBuilder.DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.Run);<b> // Определить имя модуля.</b>ModuleBuilder module =builder.DefineDynamicModule("MyAssembly");<b> // Определить открытый класс по имени HelloWorld.</b>TypeBuilder helloWorldClass =module.DefineType("MyAssembly.HelloWorld",TypeAttributes.Public);<b> // Определить закрытую переменную-член типа String по имени theMessage.</b>FieldBuilder msgField = helloWorldClass.DefineField("theMessage",Type.GetType("System.String"),attributes: FieldAttributes.Private);<b> // Создать специальный конструктор.</b>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);
