Предположим, вы cоздали новый проект консольного приложения в Visual Studio 2005, назвав его DynAsmBuilder. Переименуйте исходный класс в MyAsmBuilder и определите статический метод с именем CreateMyAsm(). Этот единственный метод будет ответственен за следующее:
• определение характеристик динамического компоновочного блока (имя, версия и т.д.);
• реализацию тина HelloClass;
• запись компоновочного блока, сгенерированного в памяти, в физический файл.
Также отметим, что метод CreateMyAsm() использует в качестве единственного параметра тип System.AppDomain, который будет использоваться для получения доступа к типу AssemblyBuilder, связанному с текущим доменом приложения (см. главу 13, где обсуждаются домены приложений .NET). Вот полный программный код, с последующим анализом.
// Вызывающая сторона посылает тип AppDomain.
public static void CreateMyAsm(AppDomain currAppDomain) {
// Установка общих характеристик компоновочного блока.
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "MyAssembly";
assemblyName.Version = new Version("1.0.0.0");
// Создание нового компоновочного блока
// в рамках текущего домена приложения.
AssemblyBuilder assembly = curAppDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save);
// Поскольку создается одномодульный компоновочный блок,
// имя модуля будет совпадать с именем компоновочного блока.
ModuleBuilder module = assembly.DefineDynamicModule("MyAssembly", "MyAssemblу.dll");
// Определение открытого класса с именем "HelloWorld".
TypeBuilder helloWorldClass = module.DefineType("MyAssembly.HelloWorld", TypeAttributes.Public);
// Определение приватной переменной String с именем "theMessage".
FieldBuilder msgField = helloWorldClass.DefineField("theMessage", Type.GetType("System.String"), FieldAttributes.Private);
// Создание пользовательского конструктора.
Type[] constructorArgs = new Type[1];
constructorArgs[0] = typeof(string);
ConstructorBuilder constructor = helloWorldClass.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, constructorArgs);
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);
constructorIL.Emit(Opcodes.Ldarg_0);
constructorIL.Emit(Opcodes.Ldarg_1);
constructorIL.Emit(OpCodes.Stfld, msgField);
constructorIL.Emit(OpCodes.Ret);
// Создание конструктора, заданного по умолчанию.
helloWorldClass.DefineDefaultConstructor(MethodAttributes.Public);
// Теперь создание метода GetMsg().
MethodBuilder getMsgMethod = helloWorldClass.DefineMethod("GetMsg", MethodAttributes.Public, typeof(string), null);
ILGenerator methodIL = getMsgMethod.GetILGenerator();
methodIL.Emit(OpCodes.Ldarg_0);
methodIL.Emit(OpCodes.Ldfld, msgField);
methodIL.Emit(Opcodes.Ret);
// Создание метода SayHello.