2013-05-07 5 views
5

Ich hoffe, jemand kann mich in die richtige Richtung mit dem folgenden Problem zeigen.Erstellen Sie einen Konstruktoraufruf mit Reflection Emit, die einen Func <> als Parameter übergibt.

Ich arbeite an einem Projekt, wo die Typen mit Reflection.Emit erzeugt werden, alles funktioniert gut, bis eine Anforderung entstand, wo ich eine Func <> in einen Konstruktor eines neuen Objekts wie folgt übergeben musste.

public class SearchTerm : IEntity 
{ 
    private readonly NavigationProperty<Item> _item; 

    public SearchTerm() 
    { 
     _item = new NavigationProperty<Item>(() => ItemIds); 
    } 
    public string[] ItemIds { get; set; } 
} 

LINQPad I kann der IL-Ausgang zu sehen ist wie folgt:

SearchTerm.<.ctor>b__0: 
IL_0000: ldarg.0  
IL_0001: call  UserQuery+SearchTerm.get_ItemIds 
IL_0006: stloc.0  // CS$1$0000 
IL_0007: br.s  IL_0009 
IL_0009: ldloc.0  // CS$1$0000 
IL_000A: ret   

SearchTerm..ctor: 
IL_0000: ldnull  
IL_0001: stloc.0  
IL_0002: ldarg.0  
IL_0003: call  System.Object..ctor 
IL_0008: nop   
IL_0009: nop   
IL_000A: ldarg.0  
IL_000B: ldloc.0  
IL_000C: brtrue.s IL_001D 
IL_000E: ldarg.0  
IL_000F: ldftn  UserQuery+SearchTerm.<.ctor>b__0 
IL_0015: newobj  System.Func<System.Collections.Generic.IEnumerable<System.String>>..ctor 
IL_001A: stloc.0  
IL_001B: br.s  IL_001D 
IL_001D: ldloc.0  
IL_001E: newobj  UserQuery<UserQuery+Item>+NavigationProperty`1..ctor 
IL_0023: stfld  UserQuery+SearchTerm._item 
IL_0028: nop   
IL_0029: ret 

Das Problem, das ich habe ist, dass ich nicht sicher bin, wie der Delegaten in IL zu definieren.

Ich habe das versucht folgende

var method = typeBuilder.DefineMethod("func", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(IEnumerable<string>), Type.EmptyTypes); 

var methodIl = method.GetILGenerator(); 
methodIl.Emit(OpCodes.Ldarg_0); 
methodIl.Emit(OpCodes.Call, dictionary["get_ItemIds"]); 
methodIl.Emit(OpCodes.Ret); 

Dann folgt der den Delegierten zu erstellen versuchen Würfen „Nicht unterstützt Exception“ mit dem Fehler „Abgeleitete Klassen müssen eine Implementierung zur Verfügung stellen.“

var funcType = typeof(Func<,>).MakeGenericType(typeBuilder, typeof(IEnumerable<string>)); 
method.CreateDelegate(funcType); 

Ich habe auch versucht Delegate.CreateDelegate und Dynamic verwendet, die sowohl die Art erfordern, bevor Sie sie erstellt wurden.

Jeder Vorschlag, was ich falsch machen könnte, wird sehr geschätzt.

Antwort

2

Wenn Sie Ihren Code aufrufen möchten, müssen Sie mit Type s und MethodInfo s arbeiten, nicht TypeBuilder s und MethodBuilder s.

So müssen Sie CreateType() und verwenden Sie dann, dass Type und seine Methode:

var generatedType = typeBuilder.CreateType(); 

var funcType = typeof(Func<,>).MakeGenericType(
    generatedType, typeof(IEnumerable<string>)); 
var d = generatedType.GetMethod("func").CreateDelegate(funcType); 
+0

So kippen Sie einen Delegaten erstellen, bis Sie die tatsächliche Art haben? Nur um die Class SearchTerm zu bestätigen, die ich gerade mit dem Typebuilder erzeuge, wäre es nicht möglich, _item = new NavigationProperty zu enthalten (() => ItemIds); weil ich createType aufrufen müsste, um die Eigenschaften der Klasse im Delegaten zu verwenden. BTW danke für die Antwort – SCB

+0

@SCB Ich sehe nicht, warum Sie eine Instanz des Delegaten erstellen müssen, um diesen Code zu generieren. Sie müssen Code generieren, um den Delegaten zu erstellen, und nicht nur den Delegaten erstellen. – svick

+0

OK, aber mein Konstruktor für SearchTerm erstellt eine neue NavigationProperty, und ich muss etwas an diesen Objektkonstruktoraufruf übergeben. – SCB

Verwandte Themen