两个Type Builders互相打电话是非法的?

时间:2009-08-15 08:02:02

标签: c# code-generation reflection.emit

我正在生成(使用System.Reflection.Emit)两种类型:将它们称为foo,bar。捕获是,foo实例化并调用bar,bar使用foo。

当我创建bar时,一切正常,但是当我开始生成foo时,我得到typeloadexception,说找不到类型foo。当我尝试将构造函数定位到bar时,它会发生(可能,因为错误是模糊的),因为它的一个参数需要foo。

当bar是foo中的嵌套类型时,这是有效的。

所以我的问题是 - 让两种类型的人像这样互相打电话,或者我做错了吗?

1 个答案:

答案 0 :(得分: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等),然后写下所有的主体,允许完全循环的代码。