2009-08-15 8 views
4

Ich erzeuge (mit System.Reflection.Emit) zwei Arten: nenne sie foo, bar. Der Haken ist, foo instanziiert und ruft bar, und bar verwendet foo.zwei TypeBuilder, die sich gegenseitig illegal nennen?

Alles funktioniert gut, wenn ich bar, aber wenn ich foo dann erzeuge, bekomme ich typeloadexception sagen, dass Typ foo nicht gefunden werden konnte. Es passiert (wahrscheinlich, weil der Fehler vage war), wenn ich versuche, den Konstruktor in bar zu finden, was als einer seiner Parameter foo erfordert.

Dies funktioniert, wenn bar geschachtelten Typ foo ist.

Also meine Frage ist - ist es illegal zwei Typen zu haben, die sich so nennen, oder mache ich es falsch?

Antwort

2

Der Versuch, den Konstruktor manuell zu finden, kann schwierig sein, aber Sie sollten immer noch den haben, den Sie zuvor generiert haben? Hast du versucht, es zu übergeben? Ich werde versuchen, ein Beispiel zu tun ...

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

Ich zusätzlichen Code hinzufügen konnte das Ergebnis zu überprüfen, aber es ist nur einfacher, bei obj im Debugger zu sehen, und Sie können die Felder usw.

sehen

Für komplexere Fälle - vergessen Sie nicht, dass Sie brauchen nicht die Körper eines Verfahrens (IL) zu schreiben, es zu benutzen ... Sie können zunächst alle Unterschriften schreiben (DefineMethod, DefineConstructor, etc), und schreiben Sie dann alle Körper nach, vollständig zyklischen Code erlaubend.

+0

Stellt sich heraus, lag der Fehler woanders. Die Methode, die bar auf foo anrief, war geschützt, also war das Leben gut, wenn bar in foo verschachtelt war, wenn ich es herauszog, konnte es diese Methode nicht aufrufen. Ich änderte es in die Öffentlichkeit und das Leben ist wieder gut. Stellt sich heraus, SRE und 2am nicht mischen. Danke trotzdem. –

Verwandte Themen