考虑为我自己的语言制作编译器,我尝试使用 Reflection.Emit 框架生成一些 MSIL 代码。当我声明局部变量时使用 int
时它工作正常。但是,当我想声明一个尚未编译的类型的局部变量时,我遇到了麻烦,因为 DeclareLocal()
将 Type
作为参数。那是我未编译的类,比如 A
,仍然需要使用
assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemName, AssemblyBuilderAccess.RunAndSave);
module = assemblyBuilder.DefineDynamicModule(Filename);
module.DefineType(name, TypeAttributes.Public | TypeAttributes.Class)
那么我将如何编译以下程序
class A {
void M() { B b = new B(); }
}
class B
void M() { A a = new A(); }
}
最佳答案
您在这里需要的主要见解是 TypeBuilder
派生自 Type
。因此,即使您尚未确定类型(通过调用 CreateType()
),您也可以使用它来声明另一种类型的局部变量。
我遇到的另一个障碍是未完成的 TypeBuilder
上的 GetConstructor()
不起作用(它会抛出异常)。但是,如果您显式创建默认构造函数,则可以通过 ConstructorBuilder
调用它。
static void Main()
{
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("foo"), AssemblyBuilderAccess.RunAndSave);
var module = assemblyBuilder.DefineDynamicModule("foo.dll");
var aType = module.DefineType(
"A", TypeAttributes.Public | TypeAttributes.Class);
var bType = module.DefineType(
"B", TypeAttributes.Public | TypeAttributes.Class);
var aCtor = aType.DefineDefaultConstructor(MethodAttributes.Public);
var bCtor = bType.DefineDefaultConstructor(MethodAttributes.Public);
CreateMethodM(aType, bType, bCtor);
CreateMethodM(bType, aType, aCtor);
aType.CreateType();
bType.CreateType();
assemblyBuilder.Save("foo.dll");
}
static void CreateMethodM(
TypeBuilder thisType, Type otherType, ConstructorInfo otherCtor)
{
var method = thisType.DefineMethod(
"M", MethodAttributes.Private, typeof(void), Type.EmptyTypes);
var il = method.GetILGenerator();
var local = il.DeclareLocal(otherType);
il.Emit(OpCodes.Newobj, otherCtor);
il.Emit(OpCodes.Stloc, local);
il.Emit(OpCodes.Ret);
}
关于c# - ILGenerator.DeclareLocal() 采用尚未编译的类的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12432998/