2013-05-07 14 views
5

Spero che qualcuno possa indicarmi la giusta direzione con il seguente problema.Creare una chiamata di costruttore utilizzando Reflection Emit che passa un Func <> come parametro

Sto lavorando a un progetto in cui i tipi vengono generati utilizzando Reflection.Emit, tutto ha funzionato bene fino a quando non è sorto un requisito in cui dovevo passare un Func <> in un costruttore di un nuovo oggetto come di seguito.

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

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

Utilizzando LINQPad posso vedere l'output IL è il seguente:

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 

Il problema che ho è che non sono sicuro di come definire il delegato all'interno di IL.

Ho provato quanto segue

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

Poi cercando di creare il delegato il seguente getta "non supportato eccezione" con l'errore "Le classi derivate devono fornire un'implementazione."

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

ho anche provato ad utilizzare Delegate.CreateDelegate e DynamicMethod che entrambi richiedono il tipo sia stato creato prima del loro utilizzo.

Qualsiasi suggerimento su quello che potrei fare male è molto apprezzato.

risposta

2

Se si vuole invocare il codice, è necessario lavorare con Type s e MethodInfo s, non s TypeBuilder e MethodBuilder s.

Quindi, è necessario CreateType() e quindi utilizzare tale Type e il suo metodo:

var generatedType = typeBuilder.CreateType(); 

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

quindi potete creare un delegato fino ad avere il tipo effettivo? Giusto per confermare la classe SearchTerm che sto attualmente generando utilizzando il typebuilder non sarei in grado di contenere _item = new NavigationProperty (() => ItemIds); perché avrei bisogno di chiamare createType per utilizzare le proprietà della classe nel delegato. BTW, grazie per la risposta – SCB

+0

@SCB Non vedo perché sarebbe necessario creare un'istanza del delegato per generare quel codice. È necessario generare codice per creare il delegato, non solo creare il delegato. – svick

+0

OK ma il mio costruttore per SearchTerm crea una nuova NavigationProperty e ho bisogno di passare qualcosa in quella chiamata del costruttore di oggetti. – SCB

Problemi correlati