如何测试两个generics是否具有基本子类关系而不实例化它们?
我有以下generics类:
class Base where T : ... { ... } class Derived : Base where T : ... { ... } class Another where T : ... { ... } class DerivedFromDerived : Derived where T : ... { ... }
在我的代码中的某处,我想测试给定的generics是否inheritance自Base
,而不创建generics的特定实例。 我怎么做?
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); }
编辑:谢谢马克。 现在我看到了光明。 我最初尝试过以下内容:
typeof(Derived).BaseType == typeof(Base)
显然,这是正确的。 但事实并非如此。 问题是Base
的T与Derived
的T不同。所以,在
typeof(Base)
Base
的T
是免费的。 但在
typeof(Derived).BaseType
Base
的T
绑定到Derived
的T
,而T
则是一个自由类型。 (这太棒了,我很乐意看到System.Reflection
的源代码!)现在,
typeof(Derived).BaseType.GetGenericTypeDefinition()
unbounds Base
的T
结论:
typeof(Derived).BaseType.GetGenericTypeDefinition() == typeof(Base)
现在,如果你们都原谅我,我的脑袋就会燃烧起来。
不确定这是否是您正在寻找的,但我认为“IsAssignableFrom”可以解决问题。
class Program { class Base { } class Derived : Base { } class Another { } class DerivedFromDerived : Derived { } static bool DerivedFromBase (Type type) { return typeof(Base ).IsAssignableFrom(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); } }
要处理开放基类型:
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; }
我想出了这个版本,虽然看起来有点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); }
它依赖于具有不同GUID的所有类型,这应该是真的,但显然下周四会发生碰撞。