检查类是否派生自泛型类

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了检查类是否派生自泛型类相关的知识,希望对你有一定的参考价值。

我的项目中有一个派生类的泛型类。

public class GenericClass<T> : GenericInterface<T>
{
}

public class Test : GenericClass<SomeType>
{
}

有没有办法找出Type对象是否来自GenericClass

t.IsSubclassOf(typeof(GenericClass<>))

不起作用。

答案

试试这个代码

static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
    while (toCheck != null && toCheck != typeof(object)) {
        var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
        if (generic == cur) {
            return true;
        }
        toCheck = toCheck.BaseType;
    }
    return false;
}
另一答案

简单的解决方案:只需为泛型类创建并添加第二个非泛型接口:

public interface IGenericClass
{
}

public class GenericClass<T> : GenericInterface<T>, IGenericClass
{
}

然后使用isasIsAssignableFrom等以任何方式检查。

if (thing is IGenericClass)
{
    // Do work
{

显然只有你能够编辑泛型类(OP似乎有)才有可能,但它比使用神秘的扩展方法更优雅和可读。

另一答案

添加到@ jaredpar的答案,这是我用来检查接口的内容:

public static bool IsImplementerOfRawGeneric(this Type type, Type toCheck)
{
    if (toCheck.GetTypeInfo().IsClass)
    {
        return false;
    }

    return type.GetInterfaces().Any(interfaceType =>
    {
        var current = interfaceType.GetTypeInfo().IsGenericType ?
                    interfaceType.GetGenericTypeDefinition() : interfaceType;
        return current == toCheck;
    });
}

public static bool IsSubTypeOfRawGeneric(this Type type, Type toCheck)
{
    return type.IsInterface ?
          IsImplementerOfRawGeneric(type, toCheck)
        : IsSubclassOfRawGeneric(type, toCheck);
}

例如:

Console.WriteLine(typeof(IList<>).IsSubTypeOfRawGeneric(typeof(IList<int>))); // true
另一答案

Fredpr,

如果我将typeof(type <>)传递给toCheck,这对我不起作用。这是我改变的。

static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
    while (toCheck != typeof(object)) {
        var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
          if (cur.IsGenericType && generic.GetGenericTypeDefinition() == cur.GetGenericTypeDefinition()) {
            return true;
        }
        toCheck = toCheck.BaseType;
    }
    return false;
}
另一答案

@EnocNRoll - Ananda Gopal的回答很有意思,但是如果事先没有实例化实例,或者你想用泛型类型定义检查,我会建议这个方法:

public static bool TypeIs(this Type x, Type d) {
    if(null==d) {
        return false;
    }

    for(var c = x; null!=c; c=c.BaseType) {
        var a = c.GetInterfaces();

        for(var i = a.Length; i-->=0;) {
            var t = i<0 ? c : a[i];

            if(t==d||t.IsGenericType&&t.GetGenericTypeDefinition()==d) {
                return true;
            }
        }
    }

    return false;
}

并使用它像:

var b = typeof(char[]).TypeIs(typeof(IList<>)); // true

t(待测试)和d都是通用类型且t==d涵盖两个案例时,有四个条件情况:(1)td都不是通用定义,或者(2)它们都是通用定义。其余案例中的一个是通用定义,只有当d已经是一般定义时,我们才有机会说td但反之亦然。

它应该与您要测试的任意类或接口一起使用,并返回与使用is运算符测试该类型的实例的内容。

另一答案
Type _type = myclass.GetType();
PropertyInfo[] _propertyInfos = _type.GetProperties();
Boolean _test = _propertyInfos[0].PropertyType.GetGenericTypeDefinition() 
== typeof(List<>);
另一答案

您可以尝试此扩展程序

    public static bool IsSubClassOfGenericClass(this Type type, Type genericClass,Type t)
    {
        return type.IsSubclassOf(genericClass.MakeGenericType(new[] { t }));
    }
另一答案

在这个游戏的后期......我也有另一个JarodPar答案的排列。

这里是Type.IsSubClassOf(Type)礼貌的反射器:

    public virtual bool IsSubclassOf(Type c)
    {
        Type baseType = this;
        if (!(baseType == c))
        {
            while (baseType != null)
            {
                if (baseType == c)
                {
                    return true;
                }
                baseType = baseType.BaseType;
            }
            return false;
        }
        return false;
    }

从那以后,我们看到它没有做任何过于克雷的事情,并且类似于JaredPar的迭代方法。到现在为止还挺好。这是我的版本(免责声明:没有经过全面测试,所以如果你发现问题就知道了)

    public static bool IsExtension(this Type thisType, Type potentialSuperType)
    {
        //
        // protect ya neck
        //
        if (thisType == null || potentialSuperType == null || thisType == potentialSuperType) return false;

        //
        // don't need to traverse inheritance for interface extension, so check/do these first
        //
        if (potentialSuperType.IsInterface)
        {
            foreach (var interfaceType in thisType.GetInterfaces())
            {
                var tempType = interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType;

                if (tempType == potentialSuperType)
                {
                    return true;
                }
            }
        }

        //
        // do the concrete type checks, iterating up the inheritance chain, as in orignal
        //
        while (thisType != null && thisType != typeof(object))
        {
            var cur = thisType.IsGenericType ? thisType.GetGenericTypeDefinition() : thisType;

            if (potentialSuperType == cur)
            {
                return true;
            }

            thisType = thisType.BaseType;
        }
        return false;
    }

基本上这只是System.Type的扩展方法 - 我这样做是为了故意将“thisType”类型限制为具体的类型,因为我的直接用法是LINQ查询“where”谓词对Type对象。我敢肯定,如果你需要的话,所有你聪明的人都可以把它变成一个高效的,多用途的静态方法:)代码做了一些事情答案的代码没有

  1. 打开一般的“扩展” - 我正在考虑继承(思考类)以及实现(接口);更改方法和参数名称以更好地反映这一点
  2. 输入空验证(meah)
  3. 相同类型的输入(类不能自己扩展)
  4. 如果有问题是接口,则短路执行;因为GetInterfaces()返回所有实现的接口(甚至是在超类中实现的接口),你可以简单地遍历该集合而不必爬上继承树

其余的与JaredPar的代码基本相同

另一答案

(由于大量重写而重新发布)

JaredPar的代码答案很棒,但是如果您的泛型类型不是基于值类型参数,那么我有一个提示会使它变得不必要。我被挂断了为什么“是”操作员不能工作,所以我也记录了我的实验结果以供将来参考。请加强此答案以进一步提高其清晰度。

小费:

如果你确定你的GenericClass实现继承了一个抽象的非泛型基类,比如GenericClassBase,你可以毫无困难地问同样的问题:

typeof(Test).IsSubclassOf(typeof(GenericClassBase))

IsSubclassOf()

我的测试表明,IsSubclassOf()不适用于无参数泛型类型,例如

typeof(GenericClass<>)

而它会合作

typeof(GenericClass<SomeType>)

因此,以下代码适用于GenericClass <>的任何派生,假设您愿意基于SomeType进行测试:

typeof(Test).IsSubclassOf(typeof(GenericClass<SomeType>))

我唯一想象你想要通过GenericClass <>进行测试的是插件框架场景。


关于“是”算子的思考

在设计时,C#不允许使用无参数泛型,因为它们在那时基本上不是完整的CLR类型。因此,您必须使用参数声明泛型变量,这就是“is”运算符对于处理对象非常强大的原因。顺便说一句,“是”运算符也不能评估无参数的泛型类型。

“is”运算符将测试整个继承链,包括接口。

因此,给定任何对象的实例,以下方法将起到作用:

bool IsTypeof<T>(object t)
{
    return (t is T);
}

这有点多余,但我想我会继续为每个人想象它。

特定

var t = new Test();

以下代码行将返回true:

bool test1 = IsTypeof<GenericInterface<SomeType>>(t);

bool test2 = IsTypeof<GenericClass<SomeType>>(t);

bool test3 = IsTypeof<Test>(t);

另一方面,如果你想要特定于Ge​​nericClass的东西,你可以使它更具体,我想,像这样:

bool IsTypeofGenericClass<SomeType>(object t)
{
    return (t is GenericClass<SomeType>);
}

然后你会像这样测试:

bool test1 = IsTypeofGenericClass<SomeType>(t);
另一答案

我研究了一些这些样本,发现在某些情况下它们缺乏。此版本适用于各种泛型:类型,接口和类型定义。

public static bool InheritsOrImplements(this Type child, Type parent)
{
    parent = ResolveGenericTypeDefinition(parent);

    var currentChild = child.IsGenericType
                        

以上是关于检查类是否派生自泛型类的主要内容,如果未能解决你的问题,请参考以下文章

检查一个类是不是派生自一个泛型类

泛型类派生子类

Java 泛型泛型用法 ( 泛型类用法 | 泛型方法用法 | 泛型通配符 ? | 泛型安全检查 )

这个嵌套类构造函数片段可以应用于泛型类吗?

显式等待-----Selenium快速入门

泛型Where T 说明