2012-09-14 48 views
7

爲我自己的語言編寫一個編譯器,我試圖用Reflection.Emit框架生成一些MSIL代碼。當我聲明局部變量時使用int時它工作正常。但是,當我想聲明一個我尚未編譯的類型的局部變量時,由於DeclareLocal()需要Type作爲參數,所以我遇到了麻煩。這是我未編譯的類,說A,仍然需要使用ILGenerator.DeclareLocal()需要一個尚未編譯的類的類型

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(); } 
} 
+0

會有什麼幫助? –

+1

@phoog:他不如等待某人做他的工作,然後...... –

+0

我實際上並沒有在C#中做這些......這只是循環依賴的一個例子 –

回答

7

你需要這裏的主要觀點是: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); 
} 
+1

啊!我的解決方案與您的解決方案非常接近!我被稱爲「t.DeclaringType」而不是簡單地稱爲「t」 –

+2

DeclaringType有些不同,它表示這種類型被聲明的類型,例如當它是嵌套類型時。 – svick

相關問題