2009-08-15 91 views
4

我生成(使用System.Reflection.Emit)兩種類型:稱他們爲富,酒吧。趕上,foo實例化並調用bar,並且bar使用foo。兩個TypeBuilders調用彼此非法?

當我創建bar時,所有的工作都很好,但是當我開始生成foo時,我得到typeloadexception表示找不到類型foo。它發生(可能,因爲錯誤是模糊的),當我試圖找到構造函數bar,作爲其參數之一使用foo。

當bar嵌套在foo中時,這起作用。

所以我的問題是 - 是不是有兩種類型互相呼叫是不合法的,還是我做錯了?

回答

2

嘗試手動查找構造函數可能很難,但是您應該仍然擁有之前生成的那個?你有沒有試過把它傳給那個?我會盡力做一個例子...

var assemblyName = new AssemblyName("tmp"); 
    var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); 
    var module = assembly.DefineDynamicModule("tmp"); 
    var foo = module.DefineType("Foo"); 
    var bar = module.DefineType("Bar"); 
    var barOnFoo = foo.DefineField("bar", bar, FieldAttributes.Private); 
    var fooOnBar = bar.DefineField("foo", foo, FieldAttributes.Private); 
    var barCtor = bar.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[] { foo }); 
    var il = barCtor.GetILGenerator(); 
    il.Emit(OpCodes.Ldarg_0); 
    il.Emit(OpCodes.Ldarg_1); 
    il.Emit(OpCodes.Stfld, fooOnBar); 
    il.Emit(OpCodes.Ret); 
    var fooCtor = foo.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Type.EmptyTypes); 
    il = fooCtor.GetILGenerator(); 
    il.Emit(OpCodes.Ldarg_0); 
    il.Emit(OpCodes.Ldarg_0); 
    il.Emit(OpCodes.Newobj, barCtor); 
    il.Emit(OpCodes.Stfld, barOnFoo); 
    il.Emit(OpCodes.Ret); 

    // create the actual types and test object creation 
    Type fooType = foo.CreateType(), barType = bar.CreateType(); 
    object obj = Activator.CreateInstance(fooType); 

我可以添加額外的代碼檢查的結果,但它更容易只是爲了看看obj在調試器,你可以看到田野等

對於更復雜的情況 - 不要忘了,你不需要寫一個方法(IL)的身體使用它......你可以先寫所有的簽名(DefineMethodDefineConstructor等),然後寫完所有的主體後,允許完全循環的代碼。

+0

原來,錯誤在其他地方撒謊。 bar在foo上調用的方法受到保護,所以當bar嵌套在foo中時,生活很好,當我將它移出時,它無法調用該方法。我將它改爲公共,生活再次美好。 結果SRE和凌晨2點不混合。 無論如何。 – 2009-08-16 19:15:34