开发者

How to test whether two generics have a base-subclass relationship without instantiating them?

I have the following generic classes:

class Base<T> where T : ... { ... }
class Derived<T> : Base<T> where T : ... { ... }
class Another<T> where T : ... { ... }
class DerivedFromDerived<T> : Derived<T> where T : ... { ... }

Somewhere in my code, I would like to test whether a given generic inherits from Base<T>, without creating a particular instance of the generic. How do I do that?

static bool DerivedFromBase(Type type) { /* ??? */ }

static void Main(string[] args)
{
    Console.WriteLine(DerivedFromBase(typeof(Derived<>)));            // true
    Console.WriteLine(DerivedFromBase(typeof(Another<>)));            // false
    Console.WriteLine(DerivedFromBase(typeof(DerivedFromDerived<>))); // true
    Console.ReadKey(true);
}

EDIT: Thank you M开发者_C百科ark. Now I see the light. I originally tried the following:

typeof(Derived<>).BaseType == typeof(Base<>)

Apparently, this is correct. But it is not. The problem is that Base's T is not the same thing as Derived's T. So, in

typeof(Base<>)

Base's T is a free type. But, in

typeof(Derived<>).BaseType

Base's T is bound to Derived's T, which is in turn a free type. (This is so awesome I would LOVE to see the System.Reflection's source code!) Now,

typeof(Derived<>).BaseType.GetGenericTypeDefinition()

unbounds Base's T. Conclusion:

typeof(Derived<>).BaseType.GetGenericTypeDefinition() == typeof(Base<>)

And now, if you all excuse me, my head is burning.


Not sure if this is what you are looking for but I think "IsAssignableFrom" will do the trick.

class Program
{
    class Base<T> { }
    class Derived<T> : Base<T> { }
    class Another<T> { }
    class DerivedFromDerived<T> : Derived<T> { }

    static bool DerivedFromBase<T>(Type type)
    {
        return typeof(Base<T>).IsAssignableFrom(type);
    }

    static void Main(string[] args)
    {
        Console.WriteLine(DerivedFromBase<int>(typeof(Derived<int>)));            // true    
        Console.WriteLine(DerivedFromBase<int>(typeof(Another<int>)));            // false    
        Console.WriteLine(DerivedFromBase<int>(typeof(DerivedFromDerived<int>))); // true   
        Console.ReadKey(true);
    }
}

To handle the open base type:

static bool DerivedFromBase(Type type)
    {
        Type openBase = typeof(Base<>);

        var baseType = type;

        while (baseType != typeof(Object) && baseType != null)
        {
            if (baseType.GetGenericTypeDefinition() == openBase) return true;

            baseType = baseType.BaseType;
        }
        return false;
    }


I've come up with this version, although it seems a little hacky.

private static bool IsDerivedFrom(Type derivedType, Type baseType)
{
    if (derivedType.BaseType == null)
        return false;

    if (derivedType.BaseType.GUID == baseType.GUID)
        return true;

    return IsDerivedFrom(derivedType.BaseType, baseType);
}

It relies on all types having different GUIDs, which should be true, but obviously a collision will happen next Thursday.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜