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.
精彩评论