progs.biz  
Начало>C#>Основы>Урок 72
C#
VB.NET
Visual C++.NET
ASP.NET
Visual C++ 6
WinAPI
C/C++
Delphi
C++ Builder
Java
SQL
PHP
DirectX
Visual Basic 6.0
Ассемблер
Интернет
Сист. прогр-ние
Pocket PC
Обзор книг
Обзор программ

С. Робинсон и др C# для профессионалов.
С. Робинсон и др C# для профессионалов.
Заказать на Озоне



Яндекс-цитирования

Основы C#
Урок 72. Reflection - динамическое создание кода

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

Для начала небольшое замечание по порядку создания соответствующих объектов. Сначала мы должны сгенерировать сборку, затем на основании этой сборки - модуль, потом на основании этого модуля - тип (например, класс), потом на основании этого типа (класса) - его члены (конструкторы, методы и т. п.). И, уже в самом конце, мы создаем непосредственно сгенерированный на предыдущих шагах тип.

Вот пример такого кода:

            // Создание имени сборки.
            AssemblyName an = new AssemblyName("MyAssembly");
            an.Version = new Version("1.0.0.0");

            // Создание сборки.            
            AssemblyBuilder ab;
            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("qqq.dll");

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

Несколько пояснений по коду.

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

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

Рассылки нашего сайта на Subscribe.Ru
Visual C++, MFC
C# и .NET
VB.NET
ASP.NET new!
Win API
C/C++
Delphi
Java
HTML, PHP, mySQL, WEB-дизайн
Flash MX
C++ Builder
Ассемблер
SQL Server
DirectX
Обзор книг
Обзор программ
Новости сайта progs.biz


 
 
Копирование любых материалов сайта без разрешения авторов и владельцев сайта запрещено.
© 2002-2008 сайт progs.biz
© 2002-2008 Игорь Алексеев