c# - ILGenerator.DeclareLocal() 采用尚未编译的类的类型

标签 c# compiler-construction cil reflection.emit

考虑为我自己的语言制作编译器,我尝试使用 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/

相关文章:

c# - 编译器为匿名方法生成了不正确的代码 [MS BUG FIXED]

c# - "yield"返回不同的类型?

c# - 在 C# 中访问泛型类型的 GenericTypeParameters

C++ 编译器输出

c# - C# 的 CodeDom 编译器

iphone - 为 IOS 编译 ffmpeg(R_ABS reloc 错误)

c# - 我可以使用 ExecuteScalar 进行更新吗?

c# - 如何在没有浏览器的情况下与网站互动?

c# - 有没有办法查看 DynamicMethod 生成的 x86 汇编代码?

c# - 带有 CIL 代码编译器的 Antlr