2009-01-12 27 views
5

Tôi muốn làm điều này:Làm thế nào để gọi một phương thức thông qua sự phản chiếu với một biểu thức lambda như một tham số?

MethodInfo m = myList.GetType().GetMethod("ConvertAll", System.Reflection.BindingFlags.InvokeMethod).MakeGenericMethod(typeof(object)); 
List<object> myConvertedList = (List<object>)m.Invoke(myList, new object[]{ (t => (object)t)}); 

myList là một danh sách chung của một loại hình cụ thể (không biết đến ứng dụng), và tôi muốn chuyển đổi nó vào một danh sách các đối tượng để làm một số hoạt động.

Tuy nhiên điều này không thành công với lỗi này: "Không thể chuyển đổi biểu thức lambda để gõ 'đối tượng' vì nó không phải là một loại đại biểu"

bạn có thể giúp tôi tìm thấy những gì là sai? Tôi đang cố gắng làm điều gì đó không thể?

Có cách nào khác để đạt được điều tương tự không?

Trả lời

5

Một biểu thức lambda là mui trần hoặc là một loại đại biểu hoặc một cây biểu hiện với chữ ký đúng - nhưng bạn cần phải xác định các đại biểu loại nó được.

Tôi nghĩ rằng mã của bạn sẽ nhiều đơn giản hơn nếu bạn thực hiện điều này một phương pháp chung:

public static List<object> ConvertToListOfObjects<T>(List<T> list) 
{ 
    return list.ConvertAll<object>(t => t); 
} 

Sau đó, bạn chỉ cần tìm và gọi rằng phương pháp tổng quát:

MethodInfo method = typeof(Foo).GetMethod("ConvertToListOfObjects", 
    BindingFlags.Static | BindingFlags.Public); 
Type listType = list.GetType().GetGenericArguments()[0]; 
MethodInfo concrete = method.MakeGenericMethod(new [] { listType }); 
List<object> objectList = (List<object>) concrete.Invoke(null, 
                new object[]{list}); 

Ví dụ hoàn chỉnh:

using System; 
using System.Reflection; 
using System.Collections.Generic; 

class Test 
{ 
    public static List<object> ConvertToListOfObjects<T>(List<T> list) 
    { 
     return list.ConvertAll<object>(t => t); 
    } 

    static void Main() 
    { 
     object list = new List<int> { 1, 2, 3, 4 }; 

     MethodInfo method = typeof(Test).GetMethod("ConvertToListOfObjects", 
      BindingFlags.Static | BindingFlags.Public); 
     Type listType = list.GetType().GetGenericArguments()[0]; 
     MethodInfo concrete = method.MakeGenericMethod(new [] { listType }); 
     List<object> objectList = (List<object>) concrete.Invoke(null, 
                new object[] {list}); 

     foreach (object o in objectList) 
     { 
      Console.WriteLine(o); 
     } 
    } 
} 
1

Một lambda tạo thành một phương pháp nhóm (về cơ bản đây là một phương pháp xác định bởi tên (và phạm vi) mà thôi. Kể từ khi phương pháp có cùng tên có thể bị quá tải, một nhóm phương pháp bao gồm các thành viên khác nhau). Điều này không thể luôn luôn ngầm được chuyển đổi thành một đại biểu bởi vì một đại biểu thực sự bị ràng buộc vào một phương thức duy nhất từ ​​bên trong một nhóm phương thức. Điều này đóng một vai trò với quá tải.

Thật không may, điều tương tự cũng áp dụng trong trường hợp của bạn. Biện pháp khắc phục là làm cho một đại biểu rõ ràng:

List<object> myConvertedList = (List<object>)m.Invoke(myList, new object[]{ new Func<YourType, object>(t => (object)t)}); 
+1

Khó khăn là YourType không được biết tại thời gian biên dịch ở đây - do đó đề xuất của tôi biến nó thành một phương pháp chung. –

+0

Ah chết tiệt, tôi không chú ý đến điều đó. –

+0

Vâng, tôi đã chuẩn bị nhận xét cùng một điều ... – juan

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