c# – 两个TypeBuilders互相打电话是非法的?

我正在生成(使用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等),然后写之后的所有实体,允许完全循环的代码.

点赞