Рейтинговые книги
Читем онлайн Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 354 355 356 357 358 359 360 361 362 ... 642

  constructorIl.Emit(OpCodes.Stfld, msgField);

  constructorIl.Emit(OpCodes.Ret);

<b>  // Создать стандартный конструктор.</b>

  helloWorldClass.DefineDefaultConstructor(

    MethodAttributes.Public);

<b>  // Создать метод GetMsg().</b>

  MethodBuilder getMsgMethod = helloWorldClass.DefineMethod(

    &quot;GetMsg&quot;,

    MethodAttributes.Public,

    typeof(string),

    null);

  ILGenerator methodIl = getMsgMethod.GetILGenerator();

  methodIl.Emit(OpCodes.Ldarg_0);

  methodIl.Emit(OpCodes.Ldfld, msgField);

  methodIl.Emit(OpCodes.Ret);

<b>  // Создать метод SayHello().</b>

  MethodBuilder sayHiMethod = helloWorldClass.DefineMethod(

    &quot;SayHello&quot;, MethodAttributes.Public, null, null);

  methodIl = sayHiMethod.GetILGenerator();

  methodIl.EmitWriteLine(&quot;Hello from the HelloWorld class!&quot;);

  methodIl.Emit(OpCodes.Ret);

<b>  // Выпустить класс HelloWorld.</b>

  helloWorldClass.CreateType();

  return builder;

}

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

Тело метода начинается с установления минимального набора характеристик сборки с применением типов AssemblyName и Version (определенных в пространстве имен System.Reflection). Затем производится получение объекта типа AssemblуBuilder через статический метод AssemblyBuilder.DefineDynamicAssembly().

При вызове метода DefineDynamicAssembly() должен быть указан режим доступа к определяемой сборке, наиболее распространенные значения которого представлены в табл. 19.9.

Следующая задача связана с определением набора модулей (и имени) для новой сборки. Метод DefineDynamicModule() возвращает ссылку на действительный объект типа ModuleBuilder:

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

  var builder = AssemblyBuilder.DefineDynamicAssembly(

    assemblyName,AssemblyBuilderAccess.Run);

Роль типа ModuleBuilder

 Тип ModuleBuilder играет ключевую роль во время разработки динамических сборок. Как и можно было ожидать, ModuleBuilder поддерживает несколько членов, которые позволяют определять набор типов, содержащихся внутри модуля (классы, интерфейсы, структуры и т.д.), а также набор встроенных ресурсов (таблицы строк, изображения и т.п.). В табл. 19.10 описаны два метода, относящиеся к созданию. (Обратите внимание, что каждый метод возвращает объект связанного типа, который представляет тип, подлежащий созданию.)

(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})

Основным членом класса ModuleBuilder является метод DefineType(). Кроме указания имени типа (в виде простой строки) с помощью перечисления System.Reflection.TypeAttributes можно описывать формат этого типа. В табл. 19.11 приведены избранные члены перечисления TypeAttributes.

Выпуск типа HelloClass и строковой переменной-члена

Теперь, когда вы лучше понимаете роль метода ModuleBuilder.CreateType(), давайте посмотрим, как можно выпустить открытый тип класса HelloWorld и закрытую строковую переменную:

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

Обратите внимание, что метод TypeBuilder.DefineField() предоставляет доступ к объекту типа FieldBuilder. В классе TypeBuilder также определены дополнительные методы, которые обеспечивают доступ к другим типам "построителей". Например, метод DefineConstructor() возвращает объект типа ConstructorBuilder, метод DefineProperty() — объект типа PropertyBuilder и т.д.

Выпуск конструкторов

Как упоминалось ранее, для определения конструктора текущего типа можно применять метод TypeBuilder.DefineConstructor(). Однако когда дело доходит до реализации конструктора HelloClass, в тело конструктора необходимо вставить низкоуровневый код CIL, который будет отвечать за присваивание входного параметра внутренней закрытой строке. Чтобы получить объект типа ILGenerator, понадобится вызвать метод GetILGenerator() из соответствующего типа "построителя" (в данном случае ConstructorBuilder).

Помещение кода CIL в реализацию членов осуществляется с помощью метода Emit() класса ILGenerator. В самом методе Emit() часто используется тип класса Opcodes, который открывает доступ к набору кодов операций CIL через свойства только для чтения. Например, свойство Opcodes.Ret обозначает возвращение из вызова метода .Opcodes.Stfid создает присваивание значения переменной-члену, a Opcodes.Call применяется для вызова заданного метода (конструктора базового класса в данном случае). Итак, логика для реализации конструктора будет выглядеть следующим образом:

1 ... 354 355 356 357 358 359 360 361 362 ... 642
На этой странице вы можете бесплатно читать книгу Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю бесплатно.
Похожие на Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю книги

Оставить комментарий