.NET/C# 判断某个类是否是泛型类型或泛型接口的子类型

栏目: ASP.NET · 发布时间: 6年前

内容简介:.NET 中提供了很多判断某个类型或实例是某个类的子类或某个接口的实现类的方法,然而这事情一旦牵扯到泛型就没那么省心了。本文将提供判断泛型接口实现或泛型类型子类的方法。对于实例,.NET 中提供了这些方法来判断:

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

本文会经常更新,请阅读原文: https://walterlv.github.io/post/is-subclass-of-raw-generic-or-implemented-raw-generic.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

.NET/C# 判断某个类是否是泛型类型或泛型接口的子类型 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://walterlv.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

HTML5经典实例

HTML5经典实例

Christopher Schmitt、Kyle Simpson / 李强 / 中国电力出版社 / 2013-7 / 48.00元

《HTML5经典实例》对于从中级到高级的Web和移动Web开发者来说是绝佳之选,它帮助你选择对你有用的HTML5功能,并且帮助你体验其他的功能。个技巧的信息十分丰富,都包含了示例代码,并详细讨论了解决方案为何有效以及如何工作。一起来看看 《HTML5经典实例》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具