.NET 中提供了很多判断某个类型或实例是某个类的子类或某个接口的实现类的方法,然而这事情一旦牵扯到泛型就没那么省心了。

本文将提供判断泛型接口实现或泛型类型子类的方法。


.NET 中没有自带的方法

对于实例,.NET 中提供了这些方法来判断:

if (instance is Foo || instance is IFoo)
{
}

对于类型,.NET 中提供了这些方法来判断:

if (typeof(Foo).IsAssignableFrom(type) || typeof(IFoo).IsAssignableFrom(type))
{
}

或者,如果不用判断接口,只判断类型的话:

if (type.IsSubClassOf(typeof(Foo)))
{
}

对于 typeof 关键字,不止可以写 typeof(Foo),还可以写 typeof(Foo<>)。这可以得到泛型版本的 Foo<T> 的类型。

不过,如果你试图拿这个泛型版本的 typeof(Foo<>) 执行上述所有判断,你会发现所有的 if 条件都会是 false

我们需要自己编写方法

typeof(Foo<>)typeof(Foo<SomeClass>) 之间的关系就是 GetGenericTypeDefinition 函数带来的关系。

所以我们可以充分利用这一点完成泛型类型的判断。

比如,我们要判断接口:

public static bool HasImplementedRawGeneric(this Type type, Type generic)
{
// 遍历类型实现的所有接口,判断是否存在某个接口是泛型,且是参数中指定的原始泛型的实例。
return type.GetInterfaces().Any(x => generic == (x.IsGenericType ? x.GetGenericTypeDefinition() : x));
}

而如果需要判断类型,那么就需要遍历此类的基类了:

public static bool IsSubClassOfRawGeneric([NotNull] this Type type, [NotNull] Type generic)
{
if (type == null) throw new ArgumentNullException(nameof(type));
if (generic == null) throw new ArgumentNullException(nameof(generic)); while (type != null && type != typeof(object))
{
isTheRawGenericType = IsTheRawGenericType(type);
if (isTheRawGenericType) return true;
type = type.BaseType;
} return false; bool IsTheRawGenericType(Type test)
=> generic == (test.IsGenericType ? test.GetGenericTypeDefinition() : test);
}

于是,我们可以把这两个方法合成一个,用于实现类似 IsAssignableFrom 的效果,不过这回将支持原始接口(也就是 typeof(Foo<>))。

/// <summary>
/// 判断指定的类型 <paramref name="type"/> 是否是指定泛型类型的子类型,或实现了指定泛型接口。
/// </summary>
/// <param name="type">需要测试的类型。</param>
/// <param name="generic">泛型接口类型,传入 typeof(IXxx&lt;&gt;)</param>
/// <returns>如果是泛型接口的子类型,则返回 true,否则返回 false。</returns>
public static bool HasImplementedRawGeneric([NotNull] this Type type, [NotNull] Type generic)
{
if (type == null) throw new ArgumentNullException(nameof(type));
if (generic == null) throw new ArgumentNullException(nameof(generic)); // 测试接口。
var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType);
if (isTheRawGenericType) return true; // 测试类型。
while (type != null && type != typeof(object))
{
isTheRawGenericType = IsTheRawGenericType(type);
if (isTheRawGenericType) return true;
type = type.BaseType;
} // 没有找到任何匹配的接口或类型。
return false; // 测试某个类型是否是指定的原始接口。
bool IsTheRawGenericType(Type test)
=> generic == (test.IsGenericType ? test.GetGenericTypeDefinition() : test);
}

.NET/C# 判断某个类是否是泛型类型或泛型接口的子类型的更多相关文章

  1. C#判断一个类中有无"指定名称"的方法

    C#中可以通过反射分析元数据来解决这个问题,示例代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 2 ...

  2. iOS 判断一个类是否存在,NSStringFromClass 不用 import 就可以获取类

    Class myCls = NSClassFromString(@"Person"); NSString *str = NSStringFromClass(myCls); if ( ...

  3. c++ 动态判断基类指针指向的子类类型(typeid)

    我们在程序中定义了一个基类,该基类有n个子类,为了方便,我们经常定义一个基类的指针数组,数组中的每一项指向都指向一个子类,那么在程序中我们如何判断这些基类指针是指向哪个子类呢? 本文提供了两种方法 ( ...

  4. 在C#中判断某个类是否实现了某个接口

    有时我们需要判断某个类是否实现了某个接口(Interface),比如在使用反射机制(Reflection)来查找特定类型的时候. 简单来说,可以使用Type.IsAssignableFrom方法: t ...

  5. 判断网络类(获取mac) InternetCheck

    using System; using System.Collections.Generic; using System.Net.NetworkInformation; using System.Ru ...

  6. 【.Net】在C#中判断某个类是否实现了某个接口

    有时我们需要判断某个类是否实现了某个接口(Interface),比如在使用反射机制(Reflection)来查找特定类型的时候. 简单来说,可以使用Type.IsAssignableFrom方法: t ...

  7. 在动态sql的使用where时,if标签判断中,如果实体类中的某一个属性是String类型,那么就可以这样来判断连接语句:

    在动态sql的使用where时,if标签判断中,如果实体类中的某一个属性是String类型,那么就可以这样来判断连接语句: 如果是String类型的字符串进行判空的时候: <if test=&q ...

  8. 实体类相同属性间赋值与如何判断实体类中是否所有的字段都为null

    1,实体类相同属性间赋值 /// <summary> /// 将实体2的值动态赋值给实体1(名称一样的属性进行赋值) /// </summary> /// <param ...

  9. Java判断一个类里是否存在某个属性

    Java判断一个类里是否存在某个属性 测试pojo类,比方我有个User类 @Getter @Setter public class User { private Long id; private S ...

随机推荐

  1. 5.6 Components -- Handling User Interaction with Actions

    1. 组件允许你定义可以在整个应用程序中重用的控件.如果它们够通用,它们也可以在被共享给其他人并且在许多应用程序中被使用. 2. 为了使一个可重用的控件有用,然而,你首先需要你的应用程序的用户和它交互 ...

  2. cocos代码研究(26)Widget子类RichView学习笔记

    理论部分 一个显示多个RichElement的容器类. 我们可以使用它很容易显示带图片的文本,继承自 Widget. 代码实践 static RichText * create ()创建一个空的Ric ...

  3. Mbps MB/S Mb/s

    以前都没有注意这几个的区别,今天百度科普了一下 所谓 10M 带宽,其实是指 10Mbps (兆比特) 1.平时所说的10m带宽,其实是指 10Mbps (兆比特)bit是计算机的最小位单位,1byt ...

  4. HDU——2955 Robberies (0-1背包)

    题意:有N个银行,每抢一个银行,可以获得\(v_i\)的前,但是会有\(p_i\)的概率被抓.现在要把被抓概率控制在\(P\)之下,求最多能抢到多少钱. 分析:0-1背包的变形,把重量变成了概率,因为 ...

  5. 正在尝试解析依赖项“MvvmLightLibs (≥ 5.2.0.0)”。 “MvvmLightLibs”已拥有为“CommonServiceLocator”定义的依赖项

    正在尝试解析依赖项"MvvmLightLibs (≥ 5.2.0.0)". "MvvmLightLibs"已拥有为"CommonServiceLoca ...

  6. bzoj1615 / P2903 [USACO08MAR]麻烦的干草打包机The Loathesome Hay Baler

    P2903 [USACO08MAR]麻烦的干草打包机The Loathesome Hay Baler 细节题.$O(n^{2})$的$bfs$可过. #include<iostream> ...

  7. 20145311实验二 "Java面向对象程序设计"

    20145311实验二 "Java面向对象程序设计" 程序设计过程 实验内容 使用单元测试.TDD的方式设计实现复数类 Complex 编写代码: 1.首先设计实现复数类 Comp ...

  8. Dijkstra算法补分

    要求 Dijkstra算法,求解附图顶点A的单源最短路径 在纸上画出求解过程,上传截图(注意图上要有自己的学号和姓名) 过程

  9. libcurl开源库在Win7 + VS2012环境下编译、配置详解 以及下载文件并显示下载进度 demo(转载)

    转载:http://blog.csdn.net/fengshuiyue/article/details/39530093(基本教程) 转载:https://my.oschina.net/u/14207 ...

  10. Bitmap 位图

    转自: http://dongxicheng.org/structure/bitmap/ 1.  概述 位图(bitmap)是一种非常常用的结构,在索引,数据压缩等方面有广泛应用.本文介绍了位图的实现 ...