检查类型是不是实现了泛型接口而不考虑泛型类型参数

Posted

技术标签:

【中文标题】检查类型是不是实现了泛型接口而不考虑泛型类型参数【英文标题】:Check if a type implements a generic interface without considering the generic type arguments检查类型是否实现了泛型接口而不考虑泛型类型参数 【发布时间】:2013-08-16 12:04:57 【问题描述】:

我有一个界面

public interface MyInterface<TKey, TValue>


实现无关紧要。现在我想检查给定类型是否是该接口的实现。此方法失败

public class MyClass : MyInterface<int, string>


但我不知道如何检查。

public void CheckIfTypeImplementsInterface(Type type)

    var result1 = typeof(MyInterface<,>).IsAssignableFrom(type); --> false
    var result2 = typeof(MyInterface<int,string>).IsAssignableFrom(type); --> true

我必须做什么才能使 result1 为真?

【问题讨论】:

您是否考虑过制作MyInterface 接口并拥有MyInterface&lt;TKey, TValue&gt; : MyInterface 【参考方案1】:

通常,只有在接口包含一些不依赖于泛型类型参数的功能时才需要这种行为。如果您可以控制接口,最好的解决方案是让类型相关部分继承自非类型相关部分。例如,如果现有的集合接口不存在,可以将它们定义为:

interface ICountable 
   CollectionAttribute Attributes get; int Count get; 
interface ICollection<T> : IEnumerable<T> ICountable
   ... and other stuff ... 

如果用ICollection 完成了这样的事情,那么期望IEnumerable&lt;Animal&gt; 但得到一个类型为CatList 的对象的代码只实现了IList&lt;Cat&gt; 使用Count 成员将没有问题对象(注意List&lt;Animal&gt; 实现了非泛型ICollection,但其他IList&lt;Animal&gt; 实现可能没有)。

事实上,如果您的任务是让代码以某种方式找到ICollection&lt;Cat&gt;Count 方法,而您期待IEnumerable&lt;Animal&gt;,那么构建类似@987654333 的东西可能是值得的@ 这样一旦你发现CatList 实现了ICollection&lt;Cat&gt;.Count,你就可以构造一个委托给一个方法,该方法将把它的参数转换为ICollection&lt;Cat&gt;,在它上面调用Count,并返回它的结果。如果您有这样的字典,那么如果您获得另一个 CatList,您将能够简单地从字典中调用委托。

【讨论】:

完全同意,但在我的情况下,我只想在属性[CustomAttribute(typeof(ClassName))] 中进行基本检查,并且我需要 ClassName 来实现接口。稍后在代码中,我知道这两个通用属性并且可以使用反射创建一个新的 ClassName 实例【参考方案2】:

据我所知,这样做的唯一方法是获取所有接口并查看泛型定义是否与所需的接口类型匹配。

bool result1 = type.GetInterfaces()
    .Where(i => i.IsGenericType)
    .Select(i => i.GetGenericTypeDefinition())
    .Contains(typeof(MyInterface<,>));

编辑:正如 Jon 在 cmets 中指出的那样,您也可以这样做:

bool result1 = type.GetInterfaces()
    .Where(i => i.IsGenericType)
    .Any(i => i.GetGenericTypeDefinition() == typeof(MyInterface<,>));

【讨论】:

您可以将最后两个更改为:.Any(i =&gt; i.GetGenericTypeDefinition() == typeof(MyInterface&lt;,&gt;)) 您可以进一步简化为一个 lambda,使用 .Any(i =&gt; i.IsGenericType &amp;&amp; i.GetGenericTypeDefinition() == typeof(MyInterface&lt;,&gt;))(不再需要 .Where,因为 .Any 已经在过滤项目)

以上是关于检查类型是不是实现了泛型接口而不考虑泛型类型参数的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin泛型 ③ ( 泛型 out 协变 | 泛型 in 逆变 | 泛型 invariant 不变 | 泛型逆变协变代码示例 | 使用 reified 关键字检查泛型参数类型 )

C#如何将类型Type作为泛型T的参数T传递

java 泛型参数具体类型获取泛型返回具体类型获取

泛型1

Gson通过借助TypeToken类来解决这个问题

泛型方法以及泛型方法泛型类的使用场景