我正在生成(使用System.Reflection.Emit)两种类型:调用它们foo,bar.问题是,foo实例化并调用bar,bar使用foo.
当我创建bar时,一切正常,但是当我开始生成foo时,我得到了typeloadexception,说找不到类型foo.当我尝试将构造函数定位到bar时,它会发生(可能,因为错误是模糊的),其中一个参数需要foo.
当bar是foo中的嵌套类型时,这种方法有效.
所以我的问题是 – 有两种类型相互呼叫是不合法的,或者我做错了吗?
最佳答案 试图手动定位构造函数可能很难,但是你仍然应该拥有之前生成的那个?你尝试过那个吗?我会尝试做一个例子……
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)来使用它…你可以先编写所有的签名(DefineMethod,DefineConstructor等),然后写之后的所有实体,允许完全循环的代码.