2009-07-13 32 views
51

Giả sử tôi có loại, MyType. Tôi muốn làm như sau:Tìm hiểu xem loại có thực hiện giao diện chung hay không

  1. Tìm hiểu xem MyType cài đặt giao diện IList, đối với một số T.
  2. Nếu câu trả lời cho (1) là có, tìm hiểu những gì T là.

Dường như cách để làm điều này là GetInterface(), nhưng điều đó chỉ cho phép bạn tìm kiếm theo tên cụ thể. Có cách nào để tìm kiếm "tất cả các giao diện có dạng IList"

liên quan (Nếu có thể nó cũng woudl thể hữu ích nếu nó làm việc nếu giao diện là một subinterface của IList.): How to determine if a type implements a specific generic interface type

Trả lời

80
// this conditional is necessary if myType can be an interface, 
// because an interface doesn't implement itself: for example, 
// typeof (IList<int>).GetInterfaces() does not contain IList<int>! 
if (myType.IsInterface && myType.IsGenericType && 
    myType.GetGenericTypeDefinition() == typeof (IList<>)) 
    return myType.GetGenericArguments()[0] ; 

foreach (var i in myType.GetInterfaces()) 
    if (i.IsGenericType && i.GetGenericTypeDefinition() == typeof (IList<>)) 
     return i.GetGenericArguments()[0] ; 

Edit: Thậm chí nếu myType thực hiện IDerivedFromList<> nhưng không trực tiếp IList<>, IList<> sẽ hiển thị trong mảng được trả về bởi GetInterfaces().

Cập nhật: thêm kiểm tra cho vỏ cạnh nơi myType là giao diện chung được đề cập.

+0

Điều này xử lý trường hợp của mảng là tốt, đó là tốt đẹp. Nếu bạn muốn thử nghiệm các mảng một cách rõ ràng thì hãy sử dụng "if (myType.IsArray) trả về myType.GetElementType();" (Và trong khi điều này có thể nhanh hơn, tôi hy vọng không có điều này là quan trọng về hiệu năng!) – yoyo

+0

Đối với những người như tôi, những người tò mò về lý do tại sao .IsInterface là cần thiết: GetGenericTypeDefinition() ném nếu nó được gọi trên một loại không chung chung. – GameFreak

+0

Thuộc tính Type.IsGenericType không có sẵn trên netstandard 1.6 và thấp hơn (và do đó không có sẵn trên .NET Core 1.0), nhưng bạn có thể sử dụng TypeInfo.IsGenericType thay thế: type.GetTypeInfo(). IsGenericType. – dotarj

0

Nếu tôi hiểu câu hỏi của bạn một cách chính xác, đây là những gì bạn đang cố gắng làm. Nếu không, vui lòng giải thích thêm.

public class MyType : ISomeInterface 
{ 
} 

MyType o = new MyType(); 

if(o is ISomeInterface) 
{ 
} 

chỉnh sửa: nếu bạn thay đổi câu hỏi của bạn, xin vui lòng thêm thực tế là bạn edited..because nay câu trả lời của tôi có vẻ như nó không thuộc về.

Trong trường hợp đó, đây là một LINQ rất lớn

  var item = typeof(MyType).GetInterfaces() 
          .Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IList<>)) 
          .Select(t => t.GetGenericArguments().First()) 
          .FirstOrDefault(); 

if(item != null) 
//it has a type 
11

Sử dụng phản xạ (và một số LINQ), bạn có thể dễ dàng làm điều này:

public static IEnumerable<Type> GetIListTypeParameters(Type type) 
{ 
    // Query. 
    return 
     from interfaceType in type.GetInterfaces() 
     where interfaceType.IsGenericType 
     let baseInterface = interfaceType.GetGenericTypeDefinition() 
     where baseInterface == typeof(IList<>) 
     select interfaceType.GetGenericArguments().First(); 
} 

Trước tiên, bạn đang nhận được các giao diện vào loại và lọc ra chỉ dành cho những người mà là một loại generic.

Sau đó, bạn nhận được định nghĩa loại chung cho các loại giao diện đó và xem liệu nó có giống như IList<> hay không.

Từ đó, việc nhận các đối số chung cho giao diện ban đầu là vấn đề đơn giản.

Hãy nhớ rằng, một loại có thể có nhiều triển khai IList<T>, đó là lý do tại sao trả lại IEnumerable<Type>.

+0

Nếu bạn quấn biểu thức trả về trong dấu ngoặc đơn và thêm một biểu thức ".First()" khác vào cuối thì nó trả về một loại thay vì độ dài 1 của IEnumerable , điều này dễ giải quyết hơn. (Cá nhân tôi nghĩ đây là một ví dụ quá thông minh với LINQ, nhưng có lẽ đó chỉ là tôi.) – yoyo

+0

@yoyo Hoặc, bạn chỉ có thể gọi 'Đầu tiên' trên kết quả của phương pháp này. Nếu bạn trả về 'First' từ phương thức này, bạn * giả sử * một tham số kiểu là hoàn toàn * sai *. – casperOne

+0

Điểm tốt @casperOne, MyType của OP có thể triển khai IList và IList . Vì vậy, câu hỏi nên có được "tìm T's" không "tìm T". Câu trả lời được chấp nhận không giải quyết vấn đề này. – yoyo

1

Là một phần mở rộng phương pháp helper

public static bool Implements<I>(this Type type, I @interface) where I : class 
{ 
    if(((@interface as Type)==null) || !(@interface as Type).IsInterface) 
     throw new ArgumentException("Only interfaces can be 'implemented'."); 

    return (@interface as Type).IsAssignableFrom(type); 
} 

ví dụ sử dụng:

var testObject = new Dictionary<int, object>(); 
result = testObject.GetType().Implements(typeof(IDictionary<int, object>)); // true! 
4
public static bool Implements<I>(this Type type) where I : class 
    { 
     if (!typeof(I).IsInterface) 
     { 
      throw new ArgumentException("Only interfaces can be 'implemented'."); 
     } 

     return typeof(I).IsAssignableFrom(type); 
    } 
1

Sử dụng đề nghị Anton Tykhyy của, đây là một phương pháp mở rộng nhỏ để kiểm tra xem một số loại thực hiện một giao diện chung với một tham số loại chung được cung cấp:

public static class ExtensionMethods 
{ 
    /// <summary> 
    /// Checks if a type has a generic interface. 
    /// For example 
    ///  mytype.HasGenericInterface(typeof(IList<>), typeof(int)) 
    /// will return TRUE if mytype implements IList<int> 
    /// </summary> 
    public static bool HasGenericInterface(this Type type, Type interf, Type typeparameter) 
    { 
     foreach (Type i in type.GetInterfaces()) 
      if (i.IsGenericType && i.GetGenericTypeDefinition() == interf) 
       if (i.GetGenericArguments()[0] == typeparameter) 
        return true; 

     return false; 
    } 
} 
Các vấn đề liên quan