sqeez3r
sqeez3r

Reputation: 515

How to determine if an object inherits from an abstract generic class

I have a generic abstract class which I derive from:

abstract class SuperClass<T>
where T : SuperDataClass

abstract class SuperDataClass

The data type is limited to SuperDataClass, so every concrete data type must inherit from SuperDataClass. In the end I have pairs of SuperClass and SuperDataClass inheriters, e.g.:

class DataClassA : SuperDataClass
class ClassA : SuperClass<DataClassA>

class DataClassB : SuperDataClass
class ClassB : SuperClass<DataClassB>

How can I check if an object, e.g. ClassA inherits from SuperClass without knowing the possible data type?

I tried the following, which does not work:

if (testObject.GetType().IsAssignableFrom(typeof(SuperClass<SuperDataClass>))) {
    Console.WriteLine("The test object inherits from SuperClass");
}

So how does the if-statement needs to look like?

Upvotes: 5

Views: 4511

Answers (4)

Matten
Matten

Reputation: 17603

Use the IsSubclassOf function in conjunction with the generic type:

if (@object.GetType().IsGenericType &&
    @object.GetType().GetGenericTypeDefinition().IsSubclassOf(typeof(SuperClass<>))) {
    Console.WriteLine("The object inherits from SuperClass");
}

Where @object is the type you want to check (i copied the naming from your question, but object is no good name because it's the superclass of all classes).

If you want to check the generic type param as well, use

if (@object.GetType().IsGenericType &&  
    @object.GetType().GenericTypeArguments[0].IsSubclassOf(typeof(SuperDataClass)) && 
    @object.GetType().IsSubclassOf(typeof(Superclass<>)))

EDIT: your last comment - non generic type deriving from generic type:

if (@object.GetType().IsSubclassOf(typeof(Superclass<>)))

Upvotes: 1

Cristian Lupascu
Cristian Lupascu

Reputation: 40576

Apparently all obvious solutions (IsSubclassOf, IsAssignableFrom, is, as) do not work in this case. So I tried to force things a bit and came up with this way of testing if a class is SuperClass<Something>:

private bool IsSuperClassOfSomeKindOfSuperDataClass(Type type)
{
    if (!type.IsGenericType)
        return false;

    var gtd = type.GetGenericTypeDefinition();

    if (gtd != typeof(SuperClass<>))
        return false;

    var genericParameter = type.GetGenericArguments().First();

    return genericParameter.IsSubclassOf(typeof(SuperDataClass));
}

Of course, this tests if a class is SuperClass<Something>, not if it inherits from SuperClass<Something>, so the next obvious step would be to write a function that tests all inheritance hierarchy for a suitable class:

private bool InheritsFromSuperClassOfSomeKindOfSuperDataClass(Type type)
{
    while (type != typeof(Object))
    {
        if (IsSuperClassOfSomeKindOfSuperDataClass(type))
            return true;

        type = type.BaseType;
    }

    return false;
}

With these functions in place, the test you're looking for is:

if (InheritsFromSuperClassOfSomeKindOfSuperDataClass(@object.GetType())) 
    // do stuff...

Upvotes: 1

xanatos
xanatos

Reputation: 111940

Recursively

Type type2 = type; // type is your type, like typeof(ClassA)

while (type2 != null)
{
    if (type2.IsGenericType && 
        type2.GetGenericTypeDefinition() == typeof(SuperClass<>))
    {
        // found
    }

    type2 = type2.BaseType;
}

Note that this won't work if you are looking for an interface!

Upvotes: 1

MoonKnight
MoonKnight

Reputation: 23831

Here you should have some clue as to what the expected type is. So in this case I would use the Type.IsSubclassOf Method.

An example of it's use is

Class1 myClass = new Class1();
DerivedC1 myDClass = new DerivedC1();
Type myClassType = myClass.GetType();
Type myDClassType = myDClass.GetType();

// Returns true.
bool isSubClass = myDClassType.IsSubclassOf(myClassType));

I hope this helps.

Upvotes: 0

Related Questions