2010-07-23 11 views
7

Tôi đã một MethodInfo thông qua vào một chức năng và tôi muốn làm như sauLàm thế nào để xác định xem một phương pháp là một trường hợp chung của một phương pháp chung

MethodInfo containsMethod = typeof(ICollection<>).GetMethod("Contains"); 
if (methodInfo.Equals(containsMethod) 
{ 
    // do something 
} 

Nhưng điều này không làm việc vì MethodInfo có một loại chung chung cụ thể. Ví dụ này không hoạt động nếu tôi biết rằng ICollection luôn là chuỗi kiểu.

MethodInfo containsMethod = typeof(ICollection<string>).GetMethod("Contains"); 
if (methodInfo.Equals(containsMethod) 
{ 
    // do something 
} 

Làm cách nào để kiểm tra xem MethodInfo có phải là kiểu ANY đã nhập của phương pháp chung mà không quan tâm loại đó là gì?

Cảm ơn.

EDIT: Câu hỏi làm rõ

Như một cách chính xác chỉ ra phương pháp này không phải là chung nhưng lớp chứa rất câu hỏi được thêm làm thế nào để tôi tìm hiểu xem MethodInfo là dành cho một loại mà là một ví dụ gõ của ICollection <>.

EDIT: bối cảnh nhiều hơn

Tôi viết một nhà cung cấp LINQ và cố gắng để xử lý "trong" trường hợp

IList<string> myList = new List<string>{ "1", "2" }; 

from Something s in ... 
where myList.Contains(s.name) 
select s; 

Trả lời

3

Bạn có thể kiểm tra các loại tuyên bố:

if(methodInfo.Name == "Contains" 
    && methodInfo.DeclaringType.IsGenericType 
    && methodInfo.DeclaringType.GetGenericTypeDefinition() == typeof(ICollection<>)) 
{ 
+0

IMO đơn giản và rõ ràng nhất, cảm ơn. –

4

Lưu ý rằng ICollection<T>.Containskhông một phương pháp chung - đó là một phi -generic phương pháp của một loại chung. Nếu không, IsGenericMethodGetGenericTypeDefinition sẽ hữu ích. Bạn có thể có được định nghĩa kiểu chung (DeclaringType.GetGenericTypeDefinition()) và làm việc trở lại lên đến Contains, nhưng tôi tự hỏi nếu bạn đang tiếp cận vấn đề này một cách khó khăn.

Thông thường, nếu bạn đang sử dụng sự phản chiếu, có thể thực dụng để thả xuống không chung chung IList - trừ khi bạn cần dữ liệu loại (ví dụ, cho siêu lập trình). Và trong trường hợp đó, tôi sẽ xem xét xem xét kỹ xem bạn có thể đơn giản hóa việc thiết lập tại đây hay không.

+0

Cảm ơn bạn đã trả lời.Thêm một số bối cảnh ở trên cho những gì tôi đang cố gắng để đạt được. Cách tiếp cận DeclaringType trông đầy hứa hẹn, tôi sẽ thử nó và quay lại. –

0

Vấn đề là bạn không có phương pháp chung: bạn có phương pháp không chung chung trên một kiểu chung. Tôi không biết cách sử dụng sự phản chiếu để đi trực tiếp từ một định nghĩa phương thức trên một kiểu generic mở tới cùng phương thức đó trên một kiểu generic đóng hoặc ngược lại. Tuy nhiên, bạn có thể tận dụng thực tế là phương pháp được trả về bởi GetMethods() trên các loại generic mở và khép kín nên luôn luôn theo đúng thứ tự và thực hiện dịch theo chỉ số:

MethodInfo containsMethod = typeof(ICollection<>).GetMethod("Contains"); 
var methodIndex = Array.IndexOf(methodInfo.DeclaringType.GetMethods(), methodInfo); 
var methodOnTypeDefinition = methodInfo.DeclaringType.GetGenericTypeDefinition().GetMethods()[methodIndex]; 
if (methodOnTypeDefinition.Equals(containsMethod)) 
{ 
    // do something 
} 
2

Một số kiểm tra lỗi sẽ cần phải được thêm vào điều này, nhưng tôi tin rằng điều này gần như không làm những gì bạn muốn. Bạn có thể sử dụng một phương thức có hoặc không có đối số kiểu làm tham số.

static bool IsContainsMethod(MethodInfo methodInfo) 
{ 
    Type[] types = { methodInfo.GetParameters().First().ParameterType }; 
    MethodInfo containsMethod = typeof(ICollection<>).MakeGenericType(types).GetMethod("Contains"); 
    return methodInfo.Equals(containsMethod); 
} 
0

thử phương pháp này

public static bool CheckGenericMethod(MethodInfo methodInfo) 
    { 
     bool areSimilarMethods = false; 
     MethodInfo methodToCompare = typeof(ISomeInterface<>).GetMethod("func"); 
     Type interfaceInfo = methodInfo.DeclaringType.GetInterface(methodToCompare.DeclaringType.FullName); 

     if (interfaceInfo != null) 
      areSimilarMethods = (methodToCompare.Name.Equals(methodInfo.Name) 
      && interfaceInfo.FullName.Contains(methodToCompare.DeclaringType.FullName)); 
     else 
     { 
      areSimilarMethods = methodToCompare.DeclaringType.Equals(methodInfo.DeclaringType); 
     } 

     return areSimilarMethods; 

    } 

và đây là việc sử dụng ví dụ đầy đủ.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Reflection; 

namespace TestReflection 
{ 
    public class Program 
    { 
     static void Main(string[] args) 
     { 
      MethodInfo info1 = typeof(ISomeInterface<>).GetMethod("func"); 
      MethodInfo info2 = typeof(MyStringCollection).GetMethod("func"); 
      MethodInfo info3 = typeof(MyProgramCollection).GetMethod("func"); 
      MethodInfo info4 = typeof(MyXCollection).GetMethod("func"); 

      if (CheckGenericMethod(info1)) Console.WriteLine("true");else Console.WriteLine("false"); 
      if (CheckGenericMethod(info2)) Console.WriteLine("true");else Console.WriteLine("false"); 
      if (CheckGenericMethod(info3)) Console.WriteLine("true");else Console.WriteLine("false"); 
      if (CheckGenericMethod(info4)) Console.WriteLine("true"); else Console.WriteLine("false"); 

      Console.ReadKey(); 
     } 


     public static bool CheckGenericMethod(MethodInfo methodInfo) 
     { 
      bool areSimilarMethods = false; 
      MethodInfo methodToCompare = typeof(ISomeInterface<>).GetMethod("func"); 
      Type interfaceInfo = methodInfo.DeclaringType.GetInterface(methodToCompare.DeclaringType.FullName); 

      if (interfaceInfo != null) 
       areSimilarMethods = (methodToCompare.Name.Equals(methodInfo.Name) 
       && interfaceInfo.FullName.Contains(methodToCompare.DeclaringType.FullName)); 
      else 
      { 
       areSimilarMethods = methodToCompare.DeclaringType.Equals(methodInfo.DeclaringType); 
      } 

      return areSimilarMethods; 

     } 
    } 

    public interface ISomeInterface<T> where T : class 
    { 
     T func(T s); 
    } 

    public class MyStringCollection : ISomeInterface<string> 
    { 
     public string func(string s) 
     { 
      return s; 
     } 
    } 

    public class MyProgramCollection : ISomeInterface<Program> 
    { 
     public Program func(Program s) 
     { 
      return s; 
     } 
    } 

    public class MyXCollection 
    { 
     public int func(int s) 
     { 
      return s; 
     } 
    } 

}