Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторные работы Java и C# технологии.doc
Скачиваний:
171
Добавлен:
01.03.2016
Размер:
3.04 Mб
Скачать
      1. Динамическое создание типов

Это ещё один приём программирования в среде .NET, тесно связанный с метаданными, и сулящий не менее революционные изменения в методах программирования.

        1. Динамическое создание программного кода

Иногда требуется динамически создать некий программный код, например класс или перечисление. Естественно, что этот код будет храниться в некоторой сборке. При этом сама динамически созданная сборка может существовать только в памяти или же может быть сохранена на диске в виде файла.

Порядок создания соответствующих объектов программного кода следующий:

  1. Сгенерировать сборку;

  2. На основе этой сборки сгенерировать модуль;

  3. На основе этого модуля сгенерировать тип (например, класс);

  4. На основе этого типа (класса) сгенерировать его члены (конструкторы, методы и т.п.);

  5. Выполнить непосредственное создание типа.

Ниже приведены два примера создания динамического кода – класса и перечисления.

        1. Динамическое создание класса

Пример создания класса по описанной выше методике.

using System;

using System.Reflection;

using System.Reflection.Emit;

// Создание имени сборки

AssemblyName an = new AssemblyName("MyAssembly");

an.Version = new Version("1.0.0.0");

// Создание сборки

ab = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Save);

// Создание модуля в сборке

ModuleBuilder mb = ab.DefineDynamicModule("MyModule", "My.dll");

// Создание типа в сборке

TypeBuilder tb = mb.DefineType("MyClass", TypeAttributes.Public);

// Создание конструктора без параметров.

ConstructorBuilder cb0 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, null);

// Добавление кода для конструктора

ILGenerator il0 = cb0.GetILGenerator();

il0.Emit(OpCodes.Ret);

// Создание конструктора с параметром типа string

ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(string)});

// Добавление кода для конструктора

ILGenerator il = cb.GetILGenerator();

il.EmitWriteLine("Constructor");

il.Emit(OpCodes.Ret);

// Непосредственное создание типа

tb.CreateType();

// Сохранение типа в файл

ab.Save("My1.dll");

Приведенный код при запуске создаст на диске файл My1.dll, в котором будет класс с 2-мя конструкторами, причем второй конструктор будет при вызове выводить строчку "Constructor".

Два пояснения по коду:

  1. Очень часто при создании типов и членов этих типов надо указать их атрибуты (модификаторы доступа типа publicи т. п.). Это мы делаем через перечисленияTypeAttributesиMethodAttributes, которое содержит соответствующие значения (Public, например). Несколько необходимых значений из этих перечислений можно соединить через побитовое "или".

  2. Метод EmitклассаILGeneratorв качестве параметра принимает перечислениеOpCodes, которое фактически содержит инструкции на языкеIL- языке, который является аналогом для .NET обычного ассемблера. Это означает, что его инструкции не столь очевидны для реального программирования - именно поэтому в качестве примера такихIL-инструкций и была приведена самая простая из них - а именно выход из функции (OpCodes.Ret).