Язык программирования C#9 и платформа .NET5 - Джепикс Филипп - Страница 359
- Предыдущая
- 359/642
- Следующая
<b>// Создать специальный конструктор, принимающий</b><b>// единственный аргумент типа string.</b>Type[] constructorArgs = new Type[1];constructorArgs[0] = typeof(string);ConstructorBuilder constructor = helloWorldClass.DefineConstructor( MethodAttributes.Public, CallingConventions.Standard, constructorArgs);<b>// Выпустить необходимый код CIL для конструктора.</b>ILGenerator constructorIl = constructor.GetILGenerator();constructorIl.Emit(OpCodes.Ldarg_0);Type objectClass = typeof(object);ConstructorInfo superConstructor = objectClass.GetConstructor(new Type[0]);constructorIl.Emit(OpCodes.Call, superConstructor);<b>// Загрузить в стек указатель this объекта.</b>constructorIl.Emit(OpCodes.Ldarg_0);constructorIl.Emit(OpCodes.Ldarg_1);<b>// Загрузить входной аргумент в виртуальный стек и сохранить его в msgField</b>constructorIl.Emit(OpCodes.Stfld, msgField);constructorIl.Emit(OpCodes.Ret);Как вам теперь уже известно, в результате определения специального конструктора для типа стандартный конструктор молча удаляется. Чтобы снова определить конструктор без аргументов, нужно просто вызвать метод
DefineDefaultConstructor()TypeBuilder<b>// Создать стандартный конструктор.</b>helloWorldClass.DefineDefaultConstructor( MethodAttributes.Public);Выпуск метода SayHello()
В заключение давайте исследуем процесс выпуска метода
SayHello()MethodBuilderhelloWorldClassILGenerator<b>// Создать метод SayHello.</b>MethodBuilder sayHiMethod = helloWorldClass.DefineMethod( "SayHello", MethodAttributes.Public, null, null);methodIl = sayHiMethod.GetILGenerator();<b>// Вывести строку на консоль.</b>methodIl.EmitWriteLine("Hello from the HelloWorld class!");methodIl.Emit(OpCodes.Ret);Здесь был определен открытый метод (т.к. указано значение
MethodAttributes.PublicnullDefineMethod()EmitWriteLine()ILGeneratorИспользование динамически сгенерированной сборки
Теперь, когда у вас есть логика для создания сборки, осталось лишь выполнить сгенерированный код. Логика в вызывающем коде обращается к методу
CreateMyAsm()AssemblyBuilder.Далее вы поупражняетесь с поздним связыванием (см. главу 17) для создания экземпляра класса
HelloWorldusing System;using System.Reflection;using System.Reflection.Emit;Console.WriteLine("***** The Amazing Dynamic Assembly Builder App *****");// Создать объект AssemblyBuilder с использованием вспомогательной функции.AssemblyBuilder builder = CreateMyAsm();// Получить тип HelloWorld.Type hello = builder.GetType("MyAssembly.HelloWorld");// Создать экземпляр HelloWorld и вызвать корректный конструктор.Console.Write("-> Enter message to pass HelloWorld class: ");string msg = Console.ReadLine();object[] ctorArgs = new object[1];ctorArgs[0] = msg;object obj = Activator.CreateInstance(hello, ctorArgs);// Вызвать метод SayHelloO и отобразить возвращенную строку.Console.WriteLine("-> Calling SayHello() via late binding.");MethodInfo mi = hello.GetMethod("SayHello");mi.Invoke(obj, null);// Вызвать метод GetMsg().mi = hello.GetMethod("GetMsg");Console.WriteLine(mi.Invoke(obj, null));Фактически только что была построена сборка .NET Core, которая способна создавать и запускать другие сборки .NET Core во время выполнения. На этом исследование языка CIL и роли динамических сборок завершено. Настоящая глава должна была помочь углубить знания системы типов .NET Core, синтаксиса и семантики языка CIL, а также способа обработки кода компилятором C# в процессе его компиляции.
- Предыдущая
- 359/642
- Следующая
