2009-07-13 77 views
51

假设我有一个类型MyType。我要做到以下几点:查明一个类型是否实现了通用接口

  1. 查找出来,如果MyType的实现IList接口,对于一些T.
  2. 如果答案(1)是肯定的,找出T是什么。

看起来像这样做的方法是GetInterface(),但它只允许您按特定名称进行搜索。有没有一种方法来搜索“是形式的IList的所有接口”

相关(如果可能的话,也woudl如果它的工作,如果接口是IList中的子接口是有用的。):How to determine if a type implements a specific generic interface type

回答

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] ; 

编辑:即使myType实现IDerivedFromList<>但不直接IList<>IList<>会出现在由GetInterfaces()返回的数组中。

更新:增加了边缘情况检查,其中myType是有问题的通用接口。

+0

这也处理数组的情况,这很好。如果你想明确地测试数组,那么使用“if(myType.IsArray)return myType.GetElementType();” (虽然这可能会更快,但我希望这些都不是性能问题!) – yoyo 2013-05-28 21:27:57

+0

对于像我这样对于需要.IsInterface的原因感兴趣的用户:GetGenericTypeDefinition()会在非泛型类型上调用时抛出。 – GameFreak 2016-10-29 01:46:53

0

如果我正确理解你的问题,这就是你正在尝试做的。如果不是,请进一步解释。

public class MyType : ISomeInterface 
{ 
} 

MyType o = new MyType(); 

if(o is ISomeInterface) 
{ 
} 

编辑:如果你改变你的问题,请添加您现在edited..because我的答案看起来像它不属于事实。

在这种情况下,这里是一个非常大的LINQ

  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

使用反射(和一些LINQ),你可以很容易地做到这一点:

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(); 
} 

首先,你所得到的类型的接口,只为那些通用型过滤掉。

然后,您将获得这些接口类型的泛型类型定义,并查看它是否与IList<>相同。

从那里,获取原始接口的通用参数是一个简单的问题。

请记住,一个类型可以有多个IList<T>实现,这就是返回IEnumerable<Type>的原因。

1

作为一个辅助方法扩展

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); 
} 

用法示例:

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

使用安东Tykhyy的建议,这里是一个小的扩展方法检查是否一些类型实现了一个通用的接口一个给定的通用类型参数:

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; 
    } 
} 
相关问题