views:

15392

answers:

7

I have a generic class in my project with derived classes.

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

public class Test : GenericClass <SomeType>
{

}

Is there any way to find out if a Type object is derived from the GenericClass ?

t.IsSubclassOf(typeof(GenericClass<>))

is not working.

+48  A: 

Try this code

static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
    while (toCheck != typeof(object)) {
        var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
        if (generic == cur) {
            return true;
        }
        toCheck = toCheck.BaseType;
    }
    return false;
}
JaredPar
thank you - this worked perfectly for me
bernhardrusch
This is a sweet piece of code, I have to say. The while loop implementation avoids the unnecessary recursion performance hit also. It's an elegant and beautiful solution to a meta-generic question.
EnocNRoll
I have added this method to my ReflectionUtils static class in my framework, and I have also adapted it as an extension method for object by defining toCheck within the method as Type toCheck = obj.GetType();given "this object obj" is the first parameter.
EnocNRoll
Perfect - just what I was looking for, thanks Jared.
Paul Suart
The while loop will not break if the toCheck type is not a class (ie, interface). This will cause a NullReferenceException.
JD Courtoy
could you have a look over this: http://stackoverflow.com/questions/2477577/how-can-i-recognize-a-generic-classfor VB.NET 2 is there something similar?
serhio
This will also return true if toCheck is the generic type you are looking for.
oillio
This only works for concrete type inheritance...Test case:bool expected = true;bool actual = Program.IsSubclassOfRawGeneric ( typeof ( IEnumerable<> ), typeof ( List<string> ) );Assert.AreEqual ( expected, actual ); // fails
Bobby
+1  A: 

JaredPar's code works but only for one level of inheritance. For unlimited levels of inheritance, use the following code

public bool IsTypeDerivedFromGenericType(Type typeToCheck, Type genericType)
{
    if (typeToCheck == typeof(object))
    {
        return false;
    }
    else if (typeToCheck == null)
    {
        return false;
    }
    else if (typeToCheck.IsGenericType && typeToCheck.GetGenericTypeDefinition() == genericType)
    {
        return true;
    }
    else
    {
        return IsTypeDerivedFromGenericType(typeToCheck.BaseType, genericType);
    }
}
+9  A: 
EnocNRoll
+5  A: 

Here's a little method I created for checking that a object is derived from a specific type. Works great for me!

internal static bool IsDerivativeOf(this Type t, Type typeToCompare)
{
    if (t == null) throw new NullReferenceException();
    if (t.BaseType == null) return false;

    if (t.BaseType == typeToCompare) return true;
    else return t.BaseType.IsDerivativeOf(typeToCompare);
}
A: 
Type _type = myclass.GetType();
PropertyInfo[] _propertyInfos = _type.GetProperties();
Boolean _test = _propertyInfos[0].PropertyType.GetGenericTypeDefinition() 
== typeof(List<>);
A: 

It might be overkill but I use extension methods like the following. They check interfaces as well as subclasses. It can also return the type that has the specified generic defintion.

E.g. for the example in the question it can test against GenericInterface as well as GenericClass. The returned type can be used with GetGenericArguments to determine that the generic argument type is "SomeType".

public static bool HasGenericDefinition(this Type type, Type definition)
{
    return GetTypeWithGenericDefinition(type, definition) != null;
}

public static Type GetTypeWithGenericDefinition(this Type type, Type definition)
{
    if (type == null)
        throw new ArgumentNullException("type");
    if (definition == null)
        throw new ArgumentNullException("genericTypeDefinition");
    if (!definition.IsGenericTypeDefinition)
        throw new ArgumentException(
            "The definition needs to be a GenericTypeDefinition", "definition");

    if (definition.IsInterface)
        foreach (var interfaceType in type.GetInterfaces())
            if (interfaceType.IsGenericType
                && interfaceType.GetGenericTypeDefinition() == definition)
                return interfaceType;

    for (Type t = type; t != null; t = t.BaseType)
        if (t.IsGenericType
            && t.GetGenericTypeDefinition() == definition)
            return t;

    return null;
}
it depends
+1  A: 

JaredPar,

This did not work for me if I pass typeof(type<>) as toCheck. Here's what I changed.

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;
}
Cirem