2009-08-15 128 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