Динамічне створення типів

Це ще один прийом програмування в середовищі .NET, тісно пов'язаний з метаданими, і що обіцяє не менш революційні зміни в методах програмування.

Динамічне створення програмного коду

Іноді потрібно динамічно створити програмний код, наприклад клас або перерахування. Природно, що цей код зберігатиметься у певній збірці. При цьому сама динамічно створена збірка може існувати тільки в пам'яті або може бути збережена на диску як файл.

Порядок створення відповідних об'єктів програмного коду наступний:

На основі цієї збірки згенерувати модуль;

На основі цього модуля згенерувати тип (наприклад, клас);

На основі цього типу (класу) згенерувати його члени (конструктори, методи тощо);

Виконати безпосереднє створення типу.

Нижче наведено два приклади створення динамічного коду – класу та перерахування.

Динамічне створення класу

Приклад створення класу за описаною вище методикою.

// Створення імені збирання

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

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

ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, новий Type[] < typeof(string)>);

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

ILGenerator il = cb.GetILGenerator();

// Безпосереднє створення типу

// Збереження типу файл

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

Два пояснення за кодом:

Дуже часто при створенні типів та членів цих типів треба вказати їх атрибути (модифікатори доступу типу public і т. п.). Це ми робимо через перерахуванняTypeAttributesіMethodAttributes, яке містить відповідні значення (Public, наприклад). Кілька необхідних значень цих перерахувань можна з'єднати через побітове "або".

Метод EmitкласуILGeneratorв якості параметра приймає перерахуванняOpCodes, яке фактично містить інструкції мовоюIL- мовою, яка є аналогом для .NET звичайного асемблера. Це означає, що його інструкції не настільки очевидні для реального програмування - саме тому як приклад такихIL-інструкцій і була наведена найпростіша з них - а саме вихід із функції (OpCodes).Ret).