Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How could I know if an object is derived from a specific generic class?

Tags:

c#

.net

generics

Suppose that I have an object then how could I know if the object is derived from a specific generic class. For example:

public class GenericClass<T> 
{
}    

public bool IsDeriveFrom(object o)
{
    return o.GetType().IsSubclassOf(typeof(GenericClass)); //will throw exception here
}

please notice that the code above will throw an exception. The type of the generic class cannot be retrieved directly because there is no type for a generic class without a type parameter provided.

like image 824
Edison Chuang Avatar asked Dec 30 '10 09:12

Edison Chuang


People also ask

How do you know if a type is generic?

To examine a generic type and its type parametersGet an instance of Type that represents the generic type. In the following code, the type is obtained using the C# typeof operator ( GetType in Visual Basic, typeid in Visual C++). See the Type class topic for other ways to get a Type object.

Can a generic class be derived from another generic class?

In the same way, you can derive a generic class from another generic class that derived from a generic interface. You may be tempted to derive just any type of class from it. One of the features of generics is that you can create a class that must implement the functionality of a certain abstract class of your choice.

How do you specify a generic class?

The declaration of a generic class is almost the same as that of a non-generic class except the class name is followed by a type parameter section. The type parameter section of a generic class can have one or more type parameters separated by commas.

Is it possible to inherit from a generic type?

An attribute cannot inherit from a generic class, nor can a generic class inherit from an attribute.


2 Answers

Your should do something like this:

    public class GenericClass<T>
    {
    }

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


    public static bool IsDeriveFrom(object o)
    {
        return o.GetType().BaseType.GetGenericTypeDefinition() == typeof(GenericClass<>);
    }

Example:

    static void Main(string[] args)
    {
        var generic = new GenericClassInherited<int>();
        var isTrue = IsDeriveFrom(generic);
    }
like image 162
Andrew Orsich Avatar answered Oct 04 '22 21:10

Andrew Orsich


bool IsDerivedFrom(Type type, Type genericBaseTypeDefinition) {
    Contract.Requires(type != null);
    Contract.Requires(genericBaseTypeDefinition != null);
    Contract.Requires(genericBaseTypeDefinition.IsGenericBaseTypeDefinition);
    Type baseType = type.BaseType;
    if (baseType == null) {
        return false;
    }

    if (baseType.IsGenericType) {
        Type generic = baseType.GetGenericTypeDefinition();
        if (generic == null) {
            return false;
        }
        return generic == genericBaseTypeDefinition;
    }

    return IsDerivedFrom(baseType, genericBaseTypeDefinition);
}

Usage:

bool derived = IsDerivedFrom(typeof(Foo), typeof(GenericFoo<>));

These tests pass:

class GenericFoo<T> { }
class DerivedGenericFoo<T> : GenericFoo<T> { }
class Foo : GenericFoo<int> { }
class Bar : Foo { }
class Animal { }

[Fact]
public void DerivedGenericFoo_derives_from_open_GenericFoo() {
    Assert.Equal(
        true,
        IsDerivedFrom(
            typeof(DerivedGenericFoo<int>),
            typeof(GenericFoo<>)
        )
    );
}

[Fact]
public void Foo_derives_from_open_GenericFoo() {
    Assert.Equal(true, IsDerivedFrom(typeof(Foo), typeof(GenericFoo<>)));
}

[Fact]
public void Bar_derives_from_open_GenericFoo() {
    Assert.Equal(true, IsDerivedFrom(typeof(Bar), typeof(GenericFoo<>)));
}

[Fact]
public void Animal_does_not_derive_from_open_GenericFoo() {
    Assert.Equal(false, IsDerivedFrom(typeof(Animal), typeof(GenericFoo<>)));
}
like image 45
jason Avatar answered Oct 04 '22 20:10

jason