代码之家  ›  专栏  ›  技术社区  ›  Krzysztof Kozmic

两个打字机制造者互相说对方非法?

  •  4
  • Krzysztof Kozmic  · 技术社区  · 16 年前

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

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

    当bar是foo中的嵌套类型时,此选项有效。

    所以我的问题是——让两种人这样互相打电话是违法的,还是我做错了?

    1 回复  |  直到 16 年前
        1
  •  2
  •   Marc Gravell    16 年前

    尝试手动定位构造函数可能很困难,但您仍然应该拥有先前生成的构造函数吗?你试过通过那一个吗?我将尝试做一个例子。。。

        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 ,等等),然后在之后写入所有正文,允许使用全循环代码。