2013-05-07 1 views
5

Я надеюсь, что кто-то может указать мне в правильном направлении со следующей проблемой.Создайте вызов конструктора, используя Reflection Emit, который передает Func <> в качестве параметра

Я работаю над проектом, в котором типы сгенерированы с использованием Reflection.Emit, все работает нормально, пока не возникло требование, когда мне нужно было передать Func <> в конструктор нового объекта, как показано ниже.

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

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

Использование LINQPad Я вижу выход IL выглядит следующим образом:

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.

Я попытался следующие

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

Затем пытаются создать делегат следующих бросков «Не поддерживается Exception» с ошибкой «Производные классы должны обеспечивать реализацию.»

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

Я также попытался с помощью Delegate.CreateDelegate и DynamicMethod которые оба требуют типа были созданы перед их использованием.

Любое предложение о том, что я могу делать неправильно, очень ценится.

ответ

2

Если вы хотите вызвать ваш код, вы должны работать с Type с и MethodInfo с, не TypeBuilder с и MethodBuilder с.

Итак, вам нужно CreateType(), а затем использовать это Type и его метод:

var generatedType = typeBuilder.CreateType(); 

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

Таким образом, вы не можете создать делегат до тех пор, пока у вас есть фактический тип? Просто чтобы подтвердить, что класс SearchTerm, который я в настоящее время генерирую с использованием typebuilder, не сможет содержать _item = new NavigationProperty (() => ItemIds); потому что мне нужно будет вызвать createType для использования свойств класса в делегате. BTW спасибо за ответ – SCB

+0

@SCB Я не понимаю, зачем вам нужно создать экземпляр делегата для создания этого кода. Вам нужно сгенерировать код для создания делегата, а не просто создать делегат. – svick

+0

OK, но мой конструктор для SearchTerm создает новый NavigationProperty, и мне нужно передать что-то в этот вызов конструктора объектов. – SCB

Смежные вопросы