Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка для КР по ООП.doc
Скачиваний:
8
Добавлен:
18.04.2019
Размер:
2.47 Mб
Скачать

Динамическая сборка: создание, сохранение, загрузка, выполнение

///-----------------------------------------------------------------------------------

/// Вот такой класс в составе однофайловой сборки DynamicAssm

/// предполагается построить в ходе выполнения сборки DynamicAssemblyGenerator.

///

/// public class DynamicTest

/// {

/// private string messageString;

/// // Конструктор

/// DynamicTest(string strKey)

/// {

/// messageString = strKey;

/// }

///

/// // Методы

/// public void ShowMessageString()

/// {

/// System.Console.WriteLine(“the value of messageString is {0}...”, messageString);

/// }

///

/// public string GetMessageString()

/// {

/// return messageString;

/// }

///

///}

///-----------------------------------------------------------------------------------

using System;

using System.Reflection;

using System.Reflection.Emit;

using System.Threading;

namespace DynamicAssemblyGenerator

{

/// <summary>

/// AssemblyGenerator - класс, реализующий динамическую генерацию сборки.

/// </summary>

class AssemblyGenerator

{

public string XXX;

public string ZZZ()

{

return XXX;

}

public int CreateAssm(AppDomain currentAppDomain)

{

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

// Для этого используется класс AssemblyName.

// Определяется имя и версия создаваемой сборки.

AssemblyName assmName = new AssemblyName();

assmName.Name = “DynamicAssm”;

assmName.Version = new Version(“1.0.0.0”);

// Создаётся сборка в памяти. В рамках текущего домена приложения.

// С использованием режима доступа, который задаётся одним из элементов перечисления:

// Run - динамическая сборка выполняется, но не сохраняется.

// RunAndSave - динамическая сборка выполняется и сохраняется.

// Save - динамическая сборка не выполненяется, но сохраняется.

AssemblyBuilder assembly = currentAppDomain.DefineDynamicAssembly(assmName,

AssemblyBuilderAccess.Save);

// Создаётся однофайловая сборка, в которой имя единственного модуля совпадает с именем самой сборки.

ModuleBuilder module = assembly.DefineDynamicModule(“DynamicAssm”,

«DynamicAssm.dll» );

// Создаётся и определяется класс DynamicTest класс. Метод module.DefineType позволяет

// встраивать в модуль класс, структуру или интерфейс.

// Вторым параметром метода идёт элемент перечисления. Таким образом создаётся объект-заготовка

// класса, который далее дополняется полями, свойствами, методами...

TypeBuilder dynamicTestClass = module.DefineType(“DynamicAssm.DynamicTest”,

TypeAttributes.Public);

// Объявляется данное-член класса DynamicTest.

// Предполагается объявить “private string messageString;”

FieldBuilder messageStringField = dynamicTestClass.DefineField(“messageString”,

Type.GetType(“System.String”),

FieldAttributes.Private);

// Объекты для генерации элементов класса. В данном конкретном случае используются при генерации:

ILGenerator bodyConstructorIL; // - тела конструктора.

ILGenerator methodIL; // - тела метода.

// Объявляется конструктор.__________________________________________________________

// Предполагается объявить «DynamicTest(string strKey)...»

Type[] constructorArgs = new Type[1];

constructorArgs[0] = Type.GetType(“System.String”);

ConstructorBuilder constructor = dynamicTestClass.DefineConstructor(

MethodAttributes.Public,

CallingConventions.Standard,

constructorArgs);

// Тело конструктора. Представляет собой IL код,

// который встраивается в тело конструктора посредством метода Emit,

// определённого в классе ILGenerator (см. Объекты для генерации элементов класса).

// Метод Emit в качестве параметров использует перечисление OpCodes (коды операций),

// которые определяют допустимые команды IL.

bodyConstructorIL = constructor.GetILGenerator();

bodyConstructorIL.Emit(OpCodes.Ldarg_0);

Type objectClass = Type.GetType(“System.Object”);

ConstructorInfo greatConstructor = objectClass.GetConstructor(new Type[0]);

bodyConstructorIL.Emit(OpCodes.Call, greatConstructor);

bodyConstructorIL.Emit(OpCodes.Ldarg_0);

bodyConstructorIL.Emit(OpCodes.Ldarg_1);

bodyConstructorIL.Emit(OpCodes.Stfld,messageStringField);

bodyConstructorIL.Emit(OpCodes.Ret);

// Конец объявления конструктора.____________________________________________________

// Объявление метода public string GetMessageString()________________________________

MethodBuilder GetMessageStringMethod = dynamicTestClass.DefineMethod(

“GetMessageString”,

MethodAttributes.Public,

Type.GetType(“System.Sring”),

null);

// IL_0000: ldarg.0

// IL_0001: ldfld string DynamicAssemblyGenerator.AssemblyGenerator::XXX

// IL_0006: stloc.0

// IL_0007: br.s IL_0009

// IL_0009: ldloc.0

// IL_000a: ret

//System.Reflection.Emit.Label label = new Label();

// Тело метода...

methodIL = GetMessageStringMethod.GetILGenerator();

methodIL.Emit(OpCodes.Ldarg_0);

methodIL.Emit(OpCodes.Ldfld,messageStringField);

methodIL.Emit(OpCodes.Ret);

// Конец объявления метода public string GetMessageString()___________________________

// Объявление метода public string ShowMessageString()________________________________

MethodBuilder ShowMessageStringMethod = dynamicTestClass.DefineMethod(

“ShowMessageString”,

MethodAttributes.Public,

null,

null);

// Тело метода...

methodIL = ShowMessageStringMethod.GetILGenerator();

methodIL.EmitWriteLine(“This is ShowMessageStringMethod...”);

methodIL.Emit(OpCodes.Ret);

// Конец объявления метода public string ShowMessageString()__________________________

// Вот и завершили динамическое объявление класса.

dynamicTestClass.CreateType();

// Остаётся его сохранить на диск.

assembly.Save(“DynamicAssm.dll”);

return 0;

}

static void Main(string[] args)

{

// Создаётся и сохраняется динамическая сборка.

AssemblyGenerator ag = new AssemblyGenerator();

ag.CreateAssm(AppDomain.CurrentDomain);

// Для наглядности! создаются НОВЫЕ объекты и заново добывается

// ссылка на текущий домен приложения.

// Теперь - дело техники. Надо загрузить и выполнить сборку.

// Делали. Умеем!

AppDomain currentAppDomain = Thread.GetDomain();

AssemblyGenerator assmGenerator = new AssemblyGenerator();

assmGenerator.CreateAssm(currentAppDomain);

// Загружаем сборку.

Assembly assm = Assembly.Load(“DynamicAssm”);

// Объект класса Type для класса DynamicTest.

Type t = assm.GetType(“DynamicAssm.DynamicTest”);

// Создаётся объект класса DynamicTest и вызывается конструктор с параметрами.

object[] argsX = new object[1];

argsX[0] = “Yes, yes, yes-s-s-s!”;

object obj = Activator.CreateInstance(t, argsX);

MethodInfo mi;

// «От имени» объекта-представителя класса DynamicTest

// вызывается метод ShowMessageString.

mi = t.GetMethod(“ShowMessageString”);

mi.Invoke(obj,null);

// «От имени» объекта-представителя класса DynamicTest

// вызывается метод GetMessageString.

// Этот метод возвращает строку, которая перехватывается

// и выводится в окне консольного приложения.

mi = t.GetMethod(“GetMessageString”);

//!!!//mi.Invoke(obj,null);//Этот метод не вызывается. Криво объявился? //

}

}

}