查找一个类是否派生自.NET中的通用类?

时间:2013-03-06 13:43:36

标签: .net generics inheritance types

我有一个类:

class A<T>
{

}

我有另一个类派生自上面的类,如:

class B : A<X>
{

}

X以上是另一个类。

现在我可以有很多像B这样的类,在这些类中,泛型参数可以是其他类。

如何判断B类之类的任何实例是否来自A类?

我试过了:

if objB.GetType() is typeof(A<object>) //didn't work, gave false

if objB.GetType() == typeof(A<object>) //didn't work, gave false

if typeof(A<object>).IsAssignableFrom(obj.GetType()) //didn't work, gave false

怎么做?

3 个答案:

答案 0 :(得分:1)

稍微误解了这个问题......这就是我在那种情况下会做的事情 - 但请注意下面的示例只能在1级深度工作。如果您认为或知道其他对象将从B派生,则循环直到BaseType为object并使用当前类型名称。或者,您可以密封B,使其无法从中获取。

    public class A<T>
    {

    }

    public class X
    {

    }

    public class B : A<X>
    {


    }


    void Test()
    {
        B obj = new B();

        if(b.GetType().BaseType.Name == "A`1")
        {
            Consosle.WriteLine(true);
        }
    }

答案 1 :(得分:1)

这是有问题的;除非您已经知道IsAssignableFrom,否则X测试不会在那里工作。你必须做类似的事情:

static bool IsA(Type type) {
    do {
        type = type.BaseType;
        if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(A<>))
           return true;
    } while(type != null && type != typeof(object));
    return false;
}

或获取T

static bool IsA(Type type, out Type t)
{
    do
    {
        type = type.BaseType;
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(A<>))
        {
            t = type.GetGenericArguments()[0];
            return true;
        }
    } while (type != null && type != typeof(object));
    t = null;
    return false;
}

答案 2 :(得分:0)

哦,这里有一些纯粹的邪恶......利用dynamic劫持反射;这里的关键点是dynamic内置了一些基于类型的缓存,所以每次都不会做繁重的工作(每种类型只有一次):

static void Main()
{
    Console.WriteLine(IsA("abc"));   // False
    Console.WriteLine(IsA(new B())); // True
    Console.WriteLine(IsA(123));     // False
    Console.WriteLine(IsA(new D())); // True - where D : B
}
public static bool IsA(object o)
{
    return (bool)EvilOnlyUseDynamicToCallThis((dynamic)o);
}

private static bool EvilOnlyUseDynamicToCallThis(object o)
{
    return false;
}
private static bool EvilOnlyUseDynamicToCallThis<T>(A<T> a)
{
    return true;
}