Литмир - Электронная Библиотека
A
A

ConstructorBuilder myCtorBuilder = /* */;

ILGenerator myCILGen = myCtorBuilder.GetILGenerator();

Имея объект

ILGenerator
, с помощью его методов можно выпускать низкоуровневые коды операций CIL. Некоторые (но не все) методы
ILGenerator
кратко описаны в табл. 19.8.

Язык программирования C#9 и платформа .NET5 - _123.png

Основным методом класса

ILGenerator
является
Emit()
, который работает в сочетании с типом
System.Reflection.Emit.Opcodes
. Как упоминалось ранее в главе, данный тип открывает доступ к множеству полей только для чтения, которые отображаются на низкоуровневые коды операций CIL. Полный набор этих членов документирован в онлайновой справочной системе, и далее в главе вы неоднократно встретите примеры их использования.

Выпуск динамической сборки

Чтобы проиллюстрировать процесс определения сборки .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(&quot;Hello from the HelloWorld class!&quot;);

  }

}

Создайте новый проект консольного приложения по имени

MyAsmBuilder
и добавьте NuGet-пакет
System.Reflection.Emit
. Импортируйте в него пространства имен
System.Reflection
и
System.Reflection.Emit
. Определите в классе
Program
статический метод по имени
CreateMyAsm()
. Этот единственный метод будет отвечать за решение следующих задач:

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

• реализация типа

HelloClass
;

• возвращение вызывающему методу объекта

AssemblyBuilder
.

Ниже приведен полный код, а затем его анализ:

static AssemblyBuilder CreateMyAsm()

{

<b>  // Установить общие характеристики сборки.</b>

  AssemblyName assemblyName = new AssemblyName

  {

    Name = &quot;MyAssembly&quot;,

    Version = new Version(&quot;1.0.0.0&quot;)

  };

<b>  // Создать новую сборку.</b>

  var builder = AssemblyBuilder.DefineDynamicAssembly(

    assemblyName,AssemblyBuilderAccess.Run);

<b>  // Определить имя модуля.</b>

  ModuleBuilder module =

    builder.DefineDynamicModule(&quot;MyAssembly&quot;);

<b>  // Определить открытый класс по имени HelloWorld.</b>

  TypeBuilder helloWorldClass =

    module.DefineType(&quot;MyAssembly.HelloWorld&quot;,

    TypeAttributes.Public);

<b>  // Определить закрытую переменную-член типа String по имени theMessage.</b>

  FieldBuilder msgField = helloWorldClass.DefineField(

    &quot;theMessage&quot;,

    Type.GetType(&quot;System.String&quot;),

    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);

357
{"b":"847442","o":1}