Составители:
Рубрика:
В отличие от Metadata Unmanaged API, библиотека рефлексии содер-
жит средства для генерации CIL-кода. Для этого предназначен класс
ILGenerator. Он позволяет после создания объекта MethodBuilder (или
ConstructorBuilder) сгенерировать для соответствующего метода (или
конструктора) поток инструкций.
Рис. 4.6. Последовательность создания метаданных
В следующем примере библиотека рефлексии используется для гене-
рации сборки .NET, состоящей из одного глобального метода main, выво-
дящего на экран сообщение «Hello, World!»:
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
class HelloGenerator
{
static void Main(string[] args)
{
AppDomain appDomain = Thread.GetDomain();
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = “hello.exe”;
AssemblyBuilder assembly =
appDomain.DefineDynamicAssembly(
assemblyName,
AssemblyBuilderAccess.RunAndSave
);
ModuleBuilder module =
assembly.DefineDynamicModule(
“hello.exe”, “hello.exe”
Анализ кода на CIL
161
MethodInfo printer =
typeof(TestClass).GetMethod(“print”,flags);
printer.Invoke(a, null);
}
Путем внесения небольших изменений в CallMethodDemo мы можем
добиться того, что объект класса TestClass будет также создаваться через
рефлексию (с помощью вызова его конструктора):
static void CallMethodDemo2()
{
Type t = typeof(TestClass);
BindingFlags flags = (BindingFlags)
(BindingFlags.NonPublic | BindingFlags.Instance);
ConstructorInfo ctor = t.GetConstructor(new Type[0]);
MethodInfo printer = t.GetMethod(“print”,flags);
object a = ctor.Invoke(null);
printer.Invoke(a, null);
}
А теперь продемонстрируем, как через рефлексию можно получить
значение поля объекта. Это достигается путем вызова метода GetField объ-
екта класса Type:
static void GetFieldDemo()
{
TestClass a = new TestClass();
BindingFlags flags = (BindingFlags)
(BindingFlags.NonPublic |
BindingFlags.Instance);
FieldInfo val =
typeof(TestClass).GetField(“val”,flags);
Console.WriteLine(val.GetValue(a));
}
4.4.2.3. Генерация метаданных и CIL-кода
Для генерации метаданных в библиотеке рефлексии предназначены
классы пространства имен System.Reflection.Emit. Создание новой сборки
начинается с создания экземпляра класса AssemblyBuilder. Далее путем вы-
зова методов класса AssemblyBuilder создается нужное количество модулей
(объектов класса ModuleBuilder), в модулях создаются типы (объекты клас-
са TypeBuilder), а в типах – конструкторы, методы и поля (объекты классов
ConstructorBuilder, MethodBuilder и FieldBuilder, соответственно). То есть
при генерации метаданных идеология такая же, как и при чтении их из го-
товой сборки (на рис. 4.6 представлена схема, показывающая последова-
тельность создания метаданных).
160
CIL и системное программирование в Microsoft .NET
AssemblyBuilder
ModuleBuilder
TypeBuilder
ParameterBuilder
ILGenerator
FieldBuilder
MethodBuilder
ConstructorBuilder
PropertyBuilder
160 CIL и системное программирование в Microsoft .NET Анализ кода на CIL 161
MethodInfo printer = В отличие от Metadata Unmanaged API, библиотека рефлексии содер-
typeof(TestClass).GetMethod(“print”,flags); жит средства для генерации CIL-кода. Для этого предназначен класс
printer.Invoke(a, null); ILGenerator. Он позволяет после создания объекта MethodBuilder (или
} ConstructorBuilder) сгенерировать для соответствующего метода (или
Путем внесения небольших изменений в CallMethodDemo мы можем конструктора) поток инструкций.
добиться того, что объект класса TestClass будет также создаваться через
рефлексию (с помощью вызова его конструктора): AssemblyBuilder FieldBuilder
static void CallMethodDemo2()
{
Type t = typeof(TestClass);
ModuleBuilder MethodBuilder ParameterBuilder
BindingFlags flags = (BindingFlags)
(BindingFlags.NonPublic | BindingFlags.Instance);
ConstructorInfo ctor = t.GetConstructor(new Type[0]);
TypeBuilder ConstructorBuilder ILGenerator
MethodInfo printer = t.GetMethod(“print”,flags);
object a = ctor.Invoke(null);
printer.Invoke(a, null);
} PropertyBuilder
А теперь продемонстрируем, как через рефлексию можно получить
значение поля объекта. Это достигается путем вызова метода GetField объ- Рис. 4.6. Последовательность создания метаданных
екта класса Type:
static void GetFieldDemo() В следующем примере библиотека рефлексии используется для гене-
{ рации сборки .NET, состоящей из одного глобального метода main, выво-
TestClass a = new TestClass(); дящего на экран сообщение «Hello, World!»:
BindingFlags flags = (BindingFlags) using System;
(BindingFlags.NonPublic | using System.Threading;
BindingFlags.Instance); using System.Reflection;
FieldInfo val = using System.Reflection.Emit;
typeof(TestClass).GetField(“val”,flags); class HelloGenerator
Console.WriteLine(val.GetValue(a)); {
} static void Main(string[] args)
{
4.4.2.3. Генерация метаданных и CIL-кода AppDomain appDomain = Thread.GetDomain();
Для генерации метаданных в библиотеке рефлексии предназначены AssemblyName assemblyName = new AssemblyName();
классы пространства имен System.Reflection.Emit. Создание новой сборки assemblyName.Name = “hello.exe”;
начинается с создания экземпляра класса AssemblyBuilder. Далее путем вы- AssemblyBuilder assembly =
зова методов класса AssemblyBuilder создается нужное количество модулей appDomain.DefineDynamicAssembly(
(объектов класса ModuleBuilder), в модулях создаются типы (объекты клас- assemblyName,
са TypeBuilder), а в типах – конструкторы, методы и поля (объекты классов AssemblyBuilderAccess.RunAndSave
ConstructorBuilder, MethodBuilder и FieldBuilder, соответственно). То есть );
при генерации метаданных идеология такая же, как и при чтении их из го- ModuleBuilder module =
товой сборки (на рис. 4.6 представлена схема, показывающая последова- assembly.DefineDynamicModule(
тельность создания метаданных). “hello.exe”, “hello.exe”
Страницы
- « первая
- ‹ предыдущая
- …
- 85
- 86
- 87
- 88
- 89
- …
- следующая ›
- последняя »
