2009-09-10 25 views
46

Tôi muốn gọi phương thức chung của mình với một đối tượng kiểu đã cho.Cách gọi phương thức chung với một đối tượng Kiểu đã cho?

void Foo(Type t) 
{ 
    MyGenericMethod<t>(); 
} 

rõ ràng không hoạt động.

Tôi làm cách nào để nó hoạt động?

+0

Chỉ vì khó tìm: Sử dụng 'động' giúp bạn tiết kiệm từ tất cả các công việc phản chiếu dễ bị lỗi. Câu trả lời hay nhất có trong câu hỏi được tham chiếu: http://stackoverflow.com/a/22441650/143684 – ygoe

Trả lời

48

Mẫu mã của bạn sẽ không hoạt động, bởi vì phương pháp chung dự kiến ​​một định danh loại, không phải là một thể hiện của lớp Loại. Bạn sẽ phải sử dụng sự phản chiếu để làm điều đó:

public class Example { 

    public void CallingTest() 
    { 
     MethodInfo method = typeof (Example).GetMethod("Test"); 
     MethodInfo genericMethod = method.MakeGenericMethod(typeof (string)); 
     genericMethod.Invoke(this, null); 

    } 

    public void Test<T>() 
    { 
     Console.WriteLine(typeof (T).Name); 
    } 
} 

Hãy nhớ rằng điều này rất dễ vỡ, tôi muốn đề nghị tìm một mẫu khác để gọi phương pháp của bạn.

Một giải pháp hacky (có thể ai đó có thể làm cho nó một chút sạch) sẽ được sử dụng một số biểu hiện kỳ ​​diệu:

public class Example { 

    public void CallingTest() 
    { 
     MethodInfo method = GetMethod<Example>(x => x.Test<object>()); 
     MethodInfo genericMethod = method.MakeGenericMethod(typeof (string)); 
     genericMethod.Invoke(this, null); 

    } 

    public static MethodInfo GetMethod<T>(Expression<Action<T>> expr) 
    { 
     return ((MethodCallExpression) expr.Body) 
      .Method 
      .GetGenericMethodDefinition(); 
    } 

    public void Test<T>() 
    { 
     Console.WriteLine(typeof (T).Name); 
    } 
} 

Lưu ý đi qua các 'đối tượng' nhận dạng loại như một loại lý luận chung trong lambda. Không thể tìm ra cách nhanh chóng để vượt qua điều đó. Dù bằng cách nào, đây là thời gian an toàn biên dịch tôi nghĩ. Nó chỉ cảm thấy sai bằng cách nào đó:/

+0

"Chương trình" là gì? – codymanix

+0

Cái xấu của tôi, tôi đã thay đổi một số tên (được thử trong một ứng dụng giao diện C# mặc định, vì vậy lớp được gọi là Program;)) Đã sửa nó cho bạn, nó phải là tên của lớp bạn muốn gọi phương thức. –

+1

Ý tưởng tuyệt vời với các biểu thức. Tôi cũng không thể nghĩ ra một cách để chỉ một phương pháp chung mà không chỉ định ít nhất một đối số giả chung. – codymanix

-2

Cách tiếp cận này sẽ không hoạt động. Lý do tại sao Loại đó là một đối tượng thuộc loại được xác định khi chạy. Tuy nhiên bạn đang cố gắng sử dụng nó để gọi một phương thức chung chung. Kiểu cuộc gọi của phương thức chung được thiết lập tại thời gian biên dịch. Do đó một đối tượng Type không bao giờ có thể được sử dụng cho một tham số kiểu trên một phương thức chung.

+2

Vậy giải pháp là gì? Tôi cũng vào chủ đề này rất nhiều. Cảm ơn. – Tarik

15

Bạn cần sử dụng sự phản chiếu, thật không may (vì những lý do mà Jared đã đề cập). Ví dụ:

MethodInfo method = typeof(Foo).GetMethod("MyGenericMethod"); 
method = method.MakeGenericMethod(t); 
method.Invoke(this, new object[0]); 

Rõ ràng bạn muốn nhiều hơn nữa kiểm tra lỗi trong thực tế :)


Side lưu ý: MSDN địa phương của tôi không xác định rằng các tham số từ MakeGenericMethod là một mảng tham số, vì vậy tôi muốn có dự kiến ​​sẽ yêu cầu:

method = method.MakeGenericMethod(new Type[] { t }); 

nhưng có vẻ như nó một mảng tham số trong thực tế, và online MSDN docs đồng ý. Odd.

+1

argghh! Các Skeet đã cho tôi đánh bại:/ –

+0

Cảm ơn bạn đã trả lời, Jon. Nhưng tôi đã đưa ra phương pháp đúng, tại sao tôi cần phải tải chúng theo tên? Không phải là có cách an toàn hơn mà không liên quan đến tên phương pháp như dây? – codymanix

+0

Cody: Tôi đã thêm một lựa chọn khác trong câu trả lời của mình (cố gắng đánh bại Skeet) không liên quan đến chuỗi. Nó không sạch như tôi muốn, nhưng ý tưởng rõ ràng là tôi nghĩ. –

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