我想使用提供的功能动态创建程序集
System.Reflection.Emit
。该程序集应与编译以下 C# 代码所生成的程序集相同:
namespace BasicModule
{
using Prism.Ioc;
using Prism.Modularity;
public class BasicModule : IModule
{
public void OnInitialized(IContainerProvider containerProvider)
{
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
}
编译上述代码时得到的 IL 代码如下所示:
.class public auto ansi beforefieldinit BasicModule.BasicModule
extends [mscorlib]System.Object
implements [Prism]Prism.Modularity.IModule
{
} // end of class BasicModule.BasicModule
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method BasicModule::.ctor
.method public hidebysig newslot virtual final
instance void OnInitialized(class [Prism]Prism.Ioc.IContainerProvider containerProvider) cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method BasicModule::OnInitialized
.method public hidebysig newslot virtual final
instance void RegisterTypes(class [Prism]Prism.Ioc.IContainerRegistry containerRegistry) cil managed
{
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method BasicModule::RegisterTypes
我使用以下 C# 类代码动态生成程序集:
namespace EmitNewAssembly
{
using Prism.Ioc;
using Prism.Modularity;
using System;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
internal class TestAssemblyCreator
{
private const string FileName = "BasicModule.dll";
private const string ModuleName = "BasicModule";
private const string ClassName = "BasicModule";
private const MethodAttributes InterfaceMethodAttributes =
MethodAttributes.Public |
MethodAttributes.HideBySig |
MethodAttributes.NewSlot |
MethodAttributes.Virtual |
MethodAttributes.Final;
private const TypeAttributes ClassAttributes =
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.BeforeFieldInit;
public TestAssemblyCreator()
{
AssemblyName assemblyName = new AssemblyName()
{
Name = "TestAssembly",
Version = new Version(1, 2, 3, 4),
CultureInfo = CultureInfo.InvariantCulture,
};
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save);
var typeBuilder = assemblyBuilder
.DefineDynamicModule(ModuleName, FileName)
.DefineType($"{ModuleName}.{ClassName}", ClassAttributes, typeof(object), new Type[] { typeof(IModule) });
var methodBuilder = typeBuilder.DefineMethod("OnInitialized", InterfaceMethodAttributes, CallingConventions.Standard, typeof(void), new Type[] { typeof(IContainerProvider) });
methodBuilder.DefineParameter(1, ParameterAttributes.None, "containerProvider");
var ilGenerator = methodBuilder.GetILGenerator();
ilGenerator.Emit(OpCodes.Nop);
ilGenerator.Emit(OpCodes.Ret);
methodBuilder = typeBuilder.DefineMethod("RegisterTypes", InterfaceMethodAttributes, CallingConventions.Standard, typeof(void), new Type[] { typeof(IContainerRegistry) });
methodBuilder.DefineParameter(1, ParameterAttributes.None, "containerRegistry");
ilGenerator = methodBuilder.GetILGenerator();
ilGenerator.Emit(OpCodes.Nop);
ilGenerator.Emit(OpCodes.Ret);
typeBuilder.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
typeBuilder.CreateType();
assemblyBuilder.Save(FileName);
}
}
}
问题是生成的IL代码略有不同。看起来如下:
.class public auto ansi beforefieldinit BasicModule.BasicModule
extends [mscorlib]System.Object
implements [Prism]Prism.Modularity.IModule
{
} // end of class BasicModule.BasicModule
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 2
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method BasicModule::.ctor
.method public hidebysig newslot virtual final
instance void OnInitialized(class [Prism]Prism.Ioc.IContainerProvider containerProvider) cil managed
{
// Code size 2 (0x2)
.maxstack 0
IL_0000: nop
IL_0001: ret
} // end of method BasicModule::OnInitialized
.method public hidebysig newslot virtual final
instance void RegisterTypes(class [Prism]Prism.Ioc.IContainerRegistry containerRegistry) cil managed
{
// Code size 2 (0x2)
.maxstack 0
IL_0000: nop
IL_0001: ret
} // end of method BasicModule::RegisterTypes
首先,生成的构造函数包含不同的
.maxstack
,2 而不是 8,并且缺少 nop
操作码。其次,OnInitialized
和RegisterTypes
的.maxstack
都是0而不是8。
我需要如何更改我的 C# 代码,以便生成的程序集包含与原始代码完全相同的 IL 代码?
编辑:
这似乎是一个问题的原因是,如果我在 ILSpy 中打开生成的程序集,我将得到以下输出:
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2070
// Header size: 12
// Code size: 7 (0x7)
.maxstack 2
.locals init /* Signature type sequence must have at least one element. */ (
)
/* 0x0000207C 02 */ IL_0000: ldarg.0
/* 0x0000207D 280100000A */ IL_0001: call instance void [mscorlib]System.Object::.ctor()
/* 0x00002082 2A */ IL_0006: ret
} // end of method BasicModule::.ctor
.method public final hidebysig newslot virtual
instance void OnInitialized (
class [Prism]Prism.Ioc.IContainerProvider containerProvider
) cil managed
{
// Method begins at RVA 0x2050
// Header size: 12
// Code size: 2 (0x2)
.maxstack 0
.locals init /* Signature type sequence must have at least one element. */ (
)
/* 0x0000205C 00 */ IL_0000: nop
/* 0x0000205D 2A */ IL_0001: ret
} // end of method BasicModule::OnInitialized
.method public final hidebysig newslot virtual
instance void RegisterTypes (
class [Prism]Prism.Ioc.IContainerRegistry containerRegistry
) cil managed
{
// Method begins at RVA 0x2060
// Header size: 12
// Code size: 2 (0x2)
.maxstack 0
.locals init /* Signature type sequence must have at least one element. */ (
)
/* 0x0000206C 00 */ IL_0000: nop
/* 0x0000206D 2A */ IL_0001: ret
} // end of method BasicModule::RegisterTypes
.locals init /* Signature type sequence must have at least one element.
在我看来,事情确实不像应有的那样。