2013-05-07 15 views
5

Tôi hy vọng một người nào đó có thể chỉ cho tôi đi đúng hướng với vấn đề sau.Tạo một cuộc gọi hàm tạo bằng cách sử dụng Reflection Emit mà chuyển một Func <> như một tham số

Tôi đang làm việc trên một dự án mà các kiểu được tạo bằng cách sử dụng Reflection.Emit, tất cả đều hoạt động tốt cho đến khi yêu cầu phát sinh. Tôi cần phải chuyển Func < thành một hàm tạo của đối tượng mới như dưới đây.

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

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

Sử dụng LINQPad tôi có thể nhìn thấy đầu ra IL là như sau:

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 

Tôi có vấn đề là tôi không chắc chắn làm thế nào để xác định các đại biểu trong IL.

Tôi đã thử những điều sau

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

Sau đó cố gắng để tạo ra các đại biểu sau throws "Not Supported Exception" với lỗi "Lớp con phải cung cấp một thực hiện."

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

Tôi cũng đã thử sử dụng Delegate.CreateDelegate và DynamicMethod, cả hai đều yêu cầu loại đã được tạo trước khi sử dụng chúng.

Bất kỳ đề xuất nào về những gì tôi có thể làm sai đều được đánh giá cao.

Trả lời

2

Nếu bạn muốn gọi mã của bạn, bạn phải làm việc với Type s và MethodInfo s, không TypeBuilder s và MethodBuilder s.

Vì vậy, bạn cần phải CreateType() và sau đó sử dụng Type và phương pháp của nó:

var generatedType = typeBuilder.CreateType(); 

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

Vì vậy, bạn không thể tạo ra một đại biểu cho đến khi bạn có các loại thực tế? Chỉ cần xác nhận Class SearchTerm mà tôi hiện đang tạo bằng cách sử dụng trình gõ không thể chứa _item = new NavigationProperty (() => ItemIds); vì tôi sẽ cần gọi createType để sử dụng các thuộc tính của lớp trong ủy nhiệm. BTW cảm ơn cho các phản ứng – SCB

+0

@SCB Tôi không thấy lý do tại sao bạn sẽ cần phải tạo ra một thể hiện của đại biểu để tạo ra mã đó. Bạn cần tạo mã để tạo đại biểu, không chỉ tạo đại biểu. – svick

+0

OK nhưng hàm tạo của tôi cho SearchTerm tạo một NavigationProperty mới và tôi cần truyền một thứ gì đó vào trong hàm gọi hàm dựng của đối tượng đó. – SCB

Các vấn đề liên quan