2013-05-07 11 views
5

Mam nadzieję, że ktoś może wskazać mi właściwy kierunek z następującym problemem.Utwórz wywołanie konstruktora, używając Emitenta odbicia, które przechodzi Func <> jako parametr

Pracuję nad projektem, w którym typy są generowane przy użyciu Reflection.Emit, wszystko działało bez zarzutu, aż pojawiło się wymaganie, gdzie muszę przekazać Func <> do konstruktora nowego obiektu, jak poniżej.

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

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

Korzystanie LINQPad widzę wyjście IL jest następujący:

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 

Problem mam to, że nie jestem pewien, jak zdefiniować delegata wewnątrz IL.

Próbowałem następujących

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

Następnie próbuje stworzyć pełnomocnikowi następujące rzutów „nieobsługiwany wyjątek” z błędem „Klasy pochodne muszą zapewniać realizację.”

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

Próbowałem również używając Delegate.CreateDelegate i DynamicMethod których oba wymagają typu zostały stworzone przed ich użyciem.

Wszelkie sugestie dotyczące tego, co robię źle, są bardzo doceniane.

Odpowiedz

2

Jeśli chcesz wywołać kod, trzeba pracować z Type s oraz MethodInfo s, a nie TypeBuilder s oraz MethodBuilder s.

Więc trzeba CreateType() a następnie użyć tego Type a jego metoda:

var generatedType = typeBuilder.CreateType(); 

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

Więc nie można utworzyć delegata, dopóki masz rzeczywisty typ? Wystarczy, że potwierdzisz Class SearchTerm, który generuję obecnie przy użyciu typubuilder, nie będzie mógł zawierać _item = new NavigationProperty (() => ItemIds); ponieważ musiałbym wywołać metodę createType, aby użyć właściwości klasy w delegacie. BTW dzięki za odpowiedź – SCB

+0

@SCB Nie widzę powodu, dlaczego trzeba utworzyć wystąpienie delegata do generowania tego kodu. Musisz wygenerować kod, aby utworzyć delegata, a nie tylko utworzyć delegata. – svick

+0

OK, ale mój konstruktor dla SearchTerm tworzy nową właściwość NavigationProperty i muszę przekazać coś do wywołania konstruktora obiektów. – SCB

Powiązane problemy