2008-11-28 28 views
107

Chỉnh sửa:Gọi phương pháp chung với một đối số kiểu chỉ được biết tại thời điểm thực hiện

Tất nhiên mã thực sự của tôi không giống chính xác như thế này. Tôi đã cố gắng viết mã bán giả để làm cho nó rõ ràng hơn khi tôi muốn làm.

Dường như nó chỉ là những thứ sai lầm.

Vì vậy, những gì tôi thực sự muốn làm là thế này:

Method<Interface1>(); 
Method<Interface2>(); 
Method<Interface3>(); 
... 

Vâng ... Tôi nghĩ rằng có lẽ tôi có thể biến nó thành một vòng lặp sử dụng phản ánh. Vì vậy, câu hỏi là: Làm thế nào để tôi làm điều đó. Tôi có rất kiến ​​thức nông phản ánh. Vì vậy, ví dụ mã sẽ là tuyệt vời.

Kịch bản trông như thế này:

public void Method<T>() where T : class 
{} 
public void AnotherMethod() 
{ 
    Assembly assembly = Assembly.GetExecutingAssembly(); 

    var interfaces = from i in assembly.GetTypes() 
    where i.Namespace == "MyNamespace.Interface" // only interfaces stored here 
    select i; 

    foreach(var i in interfaces) 
    { 
     Method<i>(); // Get compile error here! 
    } 




Original post:

Hi!

Tôi đang cố gắng để lặp qua tất cả các giao diện trong một không gian tên và gửi chúng dưới dạng đối số cho một phương pháp chung chung như thế này:

public void Method<T>() where T : class 
{} 
public void AnotherMethod() 
{ 
    Assembly assembly = Assembly.GetExecutingAssembly(); 

    var interfaces = from i in assembly.GetTypes() 
    where i.Namespace == "MyNamespace.Interface" // only interfaces stored here 
    select i; 

    foreach(var interface in interfaces) 
    { 
     Method<interface>(); // Get compile error here! 
    } 
} 

Các lỗi tôi nhận được là "Loại tên dự kiến, nhưng tên biến địa phương tìm thấy ". Nếu tôi cố gắng

... 
    foreach(var interface in interfaces) 
    { 
     Method<interface.MakeGenericType()>(); // Still get compile error here! 
    } 
} 

tôi nhận được "Không thể áp dụng điều hành '<' để toán hạng của loại 'phương pháp nhóm' và 'System.Type" Bất kỳ ý tưởng về làm thế nào để có được xung quanh vấn đề này?

Trả lời

133

EDIT: OK, thời gian cho một chương trình ngắn nhưng đầy đủ. Câu trả lời cơ bản là như trước:

  • Tìm "mở" phương pháp chung với Type.GetMethod
  • Làm cho nó generic sử dụng MakeGenericMethod
  • Gọi nó với Invoke

Dưới đây là một số mẫu mã. Lưu ý rằng tôi đã thay đổi biểu thức truy vấn thành ký hiệu chấm - không có điểm nào khi sử dụng biểu thức truy vấn khi bạn về cơ bản chỉ có một mệnh đề where.

using System; 
using System.Linq; 
using System.Reflection; 

namespace Interfaces 
{ 
    interface IFoo {} 
    interface IBar {} 
    interface IBaz {} 
} 

public class Test 
{ 
    public static void CallMe<T>() 
    { 
     Console.WriteLine("typeof(T): {0}", typeof(T)); 
    } 

    static void Main() 
    { 
     MethodInfo method = typeof(Test).GetMethod("CallMe"); 

     var types = typeof(Test).Assembly.GetTypes() 
           .Where(t => t.Namespace == "Interfaces"); 

     foreach (Type type in types) 
     { 
      MethodInfo genericMethod = method.MakeGenericMethod(type); 
      genericMethod.Invoke(null, null); // No target, no arguments 
     } 
    } 
} 

Original câu trả lời

Hãy bỏ qua một bên những vấn đề rõ ràng gọi là "giao diện" biến để bắt đầu.

Bạn phải gọi nó bằng cách phản ánh. Điểm của Generics là đặt nhiều loại kiểm tra tại biên dịch thời gian. Bạn không biết những gì loại là lúc biên dịch-thời gian - do đó bạn đã có để sử dụng Generics.

Lấy phương pháp chung, và gọi MakeGenericMethod trên đó, sau đó gọi nó.

Loại giao diện của bạn có thực sự là chung chung không? Tôi hỏi vì bạn đang gọi điện thoại MakeGenericType vào nó, nhưng không phải đi qua trong bất kỳ đối số kiểu ... bạn đang cố gắng gọi

Method<MyNamespace.Interface<string>>(); // (Or whatever instead of string) 

hoặc

Method<MyNamespace.Interface>(); 

Nếu đó là sau này, bạn chỉ cần một gọi hàm MakeGenericMethod - không phải MakeGenericType.

+0

Tôi muốn viết phương pháp chung, dựa trên loại. Nhưng nếu tôi làm cho nó bằng cách sử dụng sự phản ánh, và sau đó stub tạo ra một, nó hiểu nó sẽ không stub những gì tôi muốn. Tôi đoán là điều đó là không thể? Hoặc là nó? Viết phương thức chung cho tất cả các loại trong danh sách ... –

+1

@Stephane: Thật khó để biết chính xác những gì bạn đang cố gắng làm. Tôi đề nghị bạn hỏi một câu hỏi mới với nhiều chi tiết hơn. –

+0

Lưu ý rằng bạn có thể nhận được "Kết hợp không rõ ràng trong phương pháp phân giải" trên 'GetMethod()'. Điều này xảy ra khi phương pháp bạn đang cố gắng có được một số tình trạng quá tải. Vì vậy, bạn cần xác định cái nào bạn muốn bằng cách sử dụng 'GetMethod (" Name ", new Type [] {arguments})' – cvsguimaraes

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