我有一个泛型类在我的项目与派生类。
public class GenericClass<T> : GenericInterface<T>
{
}
public class Test : GenericClass<SomeType>
{
}
是否有任何方法可以查明Type对象是否派生自GenericClass?
t.IsSubclassOf(typeof(GenericClass<>))
不管用。
我有一个泛型类在我的项目与派生类。
public class GenericClass<T> : GenericInterface<T>
{
}
public class Test : GenericClass<SomeType>
{
}
是否有任何方法可以查明Type对象是否派生自GenericClass?
t.IsSubclassOf(typeof(GenericClass<>))
不管用。
当前回答
贾里德帕尔
这并不为我工作,如果我通过typeof(type<>)作为检查。这是我改变的地方。
static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
while (toCheck != typeof(object)) {
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (cur.IsGenericType && generic.GetGenericTypeDefinition() == cur.GetGenericTypeDefinition()) {
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}
其他回答
JaredPar的代码可以工作,但只适用于一个继承级别。要获得无限级别的继承,请使用以下代码
public bool IsTypeDerivedFromGenericType(Type typeToCheck, Type genericType)
{
if (typeToCheck == typeof(object))
{
return false;
}
else if (typeToCheck == null)
{
return false;
}
else if (typeToCheck.IsGenericType && typeToCheck.GetGenericTypeDefinition() == genericType)
{
return true;
}
else
{
return IsTypeDerivedFromGenericType(typeToCheck.BaseType, genericType);
}
}
下面是我创建的一个小方法,用于检查对象是否派生于特定类型。对我来说太棒了!
internal static bool IsDerivativeOf(this Type t, Type typeToCompare)
{
if (t == null) throw new NullReferenceException();
if (t.BaseType == null) return false;
if (t.BaseType == typeToCompare) return true;
else return t.BaseType.IsDerivativeOf(typeToCompare);
}
这些都可以用linq轻松完成。这将找到泛型基类GenericBaseType的子类的任何类型。
IEnumerable<Type> allTypes = Assembly.GetExecutingAssembly().GetTypes();
IEnumerable<Type> mySubclasses = allTypes.Where(t => t.BaseType != null
&& t.BaseType.IsGenericType
&& t.BaseType.GetGenericTypeDefinition() == typeof(GenericBaseType<,>));
你可以试试这个扩展
public static bool IsSubClassOfGenericClass(this Type type, Type genericClass,Type t)
{
return type.IsSubclassOf(genericClass.MakeGenericType(new[] { t }));
}
在fir3rpho3nixx和David Schmitt的出色回答的基础上,我修改了他们的代码,并添加了ShouldInheritOrImplementTypedGenericInterface测试(最后一个)。
/// <summary>
/// Find out if a child type implements or inherits from the parent type.
/// The parent type can be an interface or a concrete class, generic or non-generic.
/// </summary>
/// <param name="child"></param>
/// <param name="parent"></param>
/// <returns></returns>
public static bool InheritsOrImplements(this Type child, Type parent)
{
var currentChild = parent.IsGenericTypeDefinition && child.IsGenericType ? child.GetGenericTypeDefinition() : child;
while (currentChild != typeof(object))
{
if (parent == currentChild || HasAnyInterfaces(parent, currentChild))
return true;
currentChild = currentChild.BaseType != null && parent.IsGenericTypeDefinition && currentChild.BaseType.IsGenericType
? currentChild.BaseType.GetGenericTypeDefinition()
: currentChild.BaseType;
if (currentChild == null)
return false;
}
return false;
}
private static bool HasAnyInterfaces(Type parent, Type child)
{
return child.GetInterfaces().Any(childInterface =>
{
var currentInterface = parent.IsGenericTypeDefinition && childInterface.IsGenericType
? childInterface.GetGenericTypeDefinition()
: childInterface;
return currentInterface == parent;
});
}
[Test]
public void ShouldInheritOrImplementNonGenericInterface()
{
Assert.That(typeof(FooImplementor)
.InheritsOrImplements(typeof(IFooInterface)), Is.True);
}
[Test]
public void ShouldInheritOrImplementGenericInterface()
{
Assert.That(typeof(GenericFooBase)
.InheritsOrImplements(typeof(IGenericFooInterface<>)), Is.True);
}
[Test]
public void ShouldInheritOrImplementGenericInterfaceByGenericSubclass()
{
Assert.That(typeof(GenericFooImplementor<>)
.InheritsOrImplements(typeof(IGenericFooInterface<>)), Is.True);
}
[Test]
public void ShouldInheritOrImplementGenericInterfaceByGenericSubclassNotCaringAboutGenericTypeParameter()
{
Assert.That(new GenericFooImplementor<string>().GetType()
.InheritsOrImplements(typeof(IGenericFooInterface<>)), Is.True);
}
[Test]
public void ShouldNotInheritOrImplementGenericInterfaceByGenericSubclassNotCaringAboutGenericTypeParameter()
{
Assert.That(new GenericFooImplementor<string>().GetType()
.InheritsOrImplements(typeof(IGenericFooInterface<int>)), Is.False);
}
[Test]
public void ShouldInheritOrImplementNonGenericClass()
{
Assert.That(typeof(FooImplementor)
.InheritsOrImplements(typeof(FooBase)), Is.True);
}
[Test]
public void ShouldInheritOrImplementAnyBaseType()
{
Assert.That(typeof(GenericFooImplementor<>)
.InheritsOrImplements(typeof(FooBase)), Is.True);
}
[Test]
public void ShouldInheritOrImplementTypedGenericInterface()
{
GenericFooImplementor<int> obj = new GenericFooImplementor<int>();
Type t = obj.GetType();
Assert.IsTrue(t.InheritsOrImplements(typeof(IGenericFooInterface<int>)));
Assert.IsFalse(t.InheritsOrImplements(typeof(IGenericFooInterface<String>)));
}