8

在为自己的语言制作编译器的过程中,我尝试使用 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(); }
}
4

1 回答 1

8

您在这里需要的主要洞察力TypeBuilder来自Type. 因此,即使您尚未最终确定类型(通过调用CreateType()),您也可以使用它来声明另一种类型的局部变量。

我遇到的另一个障碍是GetConstructor()在未完成TypeBuilder的情况下不起作用(它会引发异常)。但是如果显式创建默认构造函数,则可以通过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);
}
于 2012-09-14T23:35:49.010 回答