Two TypeBuilders calling each other illegal?

I generate (using System.Reflection.Emit) two types: name them foo, bar. The trap, foo instantiates and calls bar, and bar uses foo.

Everything works fine when I create a bar, but when I start to generate foo, I get a typeloadexception saying that the type foo was not found. This happens (probably because the error was unspecified) when I try to find the constructor in bar, which, as one of its parameters, takes foo.

This works when bar is a nested type in foo.

So my question is: is it illegal to have two types calling each other, or am I doing it wrong?

+4
source share
1 answer

Trying to find the constructor manually can be difficult, but you still need to have the one you created earlier? Have you tried passing this? I will try to make an example ...

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); 

I could add additional code to check the result, but it's easier to just look at obj in the debugger, and you can see the fields, etc.

For more complex cases - do not forget that you do not need to write the body of the method (IL) to use it ... you can first write all the signatures ( DefineMethod , DefineConstructor , etc.), and then write all the bodies after, allowing completely cyclic code.

+2
source

All Articles