我的项目中有一个派生类的泛型类。
public class GenericClass<T> : GenericInterface<T>
{
}
public class Test : GenericClass<SomeType>
{
}
有没有办法找出Type
对象是否来自GenericClass
?
t.IsSubclassOf(typeof(GenericClass<>))
不起作用。
试试这个代码
static bool IsSubclassOfRawGeneric(Type generic, Type toCheck) {
while (toCheck != null && toCheck != typeof(object)) {
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur) {
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}
简单的解决方案:只需为泛型类创建并添加第二个非泛型接口:
public interface IGenericClass
{
}
public class GenericClass<T> : GenericInterface<T>, IGenericClass
{
}
然后使用is
,as
,IsAssignableFrom
等以任何方式检查。
if (thing is IGenericClass)
{
// Do work
{
显然只有你能够编辑泛型类(OP似乎有)才有可能,但它比使用神秘的扩展方法更优雅和可读。
添加到@ jaredpar的答案,这是我用来检查接口的内容:
public static bool IsImplementerOfRawGeneric(this Type type, Type toCheck)
{
if (toCheck.GetTypeInfo().IsClass)
{
return false;
}
return type.GetInterfaces().Any(interfaceType =>
{
var current = interfaceType.GetTypeInfo().IsGenericType ?
interfaceType.GetGenericTypeDefinition() : interfaceType;
return current == toCheck;
});
}
public static bool IsSubTypeOfRawGeneric(this Type type, Type toCheck)
{
return type.IsInterface ?
IsImplementerOfRawGeneric(type, toCheck)
: IsSubclassOfRawGeneric(type, toCheck);
}
例如:
Console.WriteLine(typeof(IList<>).IsSubTypeOfRawGeneric(typeof(IList<int>))); // true
Fredpr,
如果我将typeof(type <>)传递给toCheck,这对我不起作用。这是我改变的。
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;
}
@EnocNRoll - Ananda Gopal的回答很有意思,但是如果事先没有实例化实例,或者你想用泛型类型定义检查,我会建议这个方法:
public static bool TypeIs(this Type x, Type d) {
if(null==d) {
return false;
}
for(var c = x; null!=c; c=c.BaseType) {
var a = c.GetInterfaces();
for(var i = a.Length; i-->=0;) {
var t = i<0 ? c : a[i];
if(t==d||t.IsGenericType&&t.GetGenericTypeDefinition()==d) {
return true;
}
}
}
return false;
}
并使用它像:
var b = typeof(char[]).TypeIs(typeof(IList<>)); // true
当t
(待测试)和d
都是通用类型且t==d
涵盖两个案例时,有四个条件情况:(1)t
和d
都不是通用定义,或者(2)它们都是通用定义。其余案例中的一个是通用定义,只有当d
已经是一般定义时,我们才有机会说t
是d
但反之亦然。
它应该与您要测试的任意类或接口一起使用,并返回与使用is
运算符测试该类型的实例的内容。
Type _type = myclass.GetType();
PropertyInfo[] _propertyInfos = _type.GetProperties();
Boolean _test = _propertyInfos[0].PropertyType.GetGenericTypeDefinition()
== typeof(List<>);
您可以尝试此扩展程序
public static bool IsSubClassOfGenericClass(this Type type, Type genericClass,Type t)
{
return type.IsSubclassOf(genericClass.MakeGenericType(new[] { t }));
}
在这个游戏的后期......我也有另一个JarodPar答案的排列。
这里是Type.IsSubClassOf(Type)礼貌的反射器:
public virtual bool IsSubclassOf(Type c)
{
Type baseType = this;
if (!(baseType == c))
{
while (baseType != null)
{
if (baseType == c)
{
return true;
}
baseType = baseType.BaseType;
}
return false;
}
return false;
}
从那以后,我们看到它没有做任何过于克雷的事情,并且类似于JaredPar的迭代方法。到现在为止还挺好。这是我的版本(免责声明:没有经过全面测试,所以如果你发现问题就知道了)
public static bool IsExtension(this Type thisType, Type potentialSuperType)
{
//
// protect ya neck
//
if (thisType == null || potentialSuperType == null || thisType == potentialSuperType) return false;
//
// don't need to traverse inheritance for interface extension, so check/do these first
//
if (potentialSuperType.IsInterface)
{
foreach (var interfaceType in thisType.GetInterfaces())
{
var tempType = interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : interfaceType;
if (tempType == potentialSuperType)
{
return true;
}
}
}
//
// do the concrete type checks, iterating up the inheritance chain, as in orignal
//
while (thisType != null && thisType != typeof(object))
{
var cur = thisType.IsGenericType ? thisType.GetGenericTypeDefinition() : thisType;
if (potentialSuperType == cur)
{
return true;
}
thisType = thisType.BaseType;
}
return false;
}
基本上这只是System.Type的扩展方法 - 我这样做是为了故意将“thisType”类型限制为具体的类型,因为我的直接用法是LINQ查询“where”谓词对Type对象。我敢肯定,如果你需要的话,所有你聪明的人都可以把它变成一个高效的,多用途的静态方法:)代码做了一些事情答案的代码没有
其余的与JaredPar的代码基本相同
(由于大量重写而重新发布)
JaredPar的代码答案很棒,但是如果您的泛型类型不是基于值类型参数,那么我有一个提示会使它变得不必要。我被挂断了为什么“是”操作员不能工作,所以我也记录了我的实验结果以供将来参考。请加强此答案以进一步提高其清晰度。
如果你确定你的GenericClass实现继承了一个抽象的非泛型基类,比如GenericClassBase,你可以毫无困难地问同样的问题:
typeof(Test).IsSubclassOf(typeof(GenericClassBase))
我的测试表明,IsSubclassOf()不适用于无参数泛型类型,例如
typeof(GenericClass<>)
而它会合作
typeof(GenericClass<SomeType>)
因此,以下代码适用于GenericClass <>的任何派生,假设您愿意基于SomeType进行测试:
typeof(Test).IsSubclassOf(typeof(GenericClass<SomeType>))
我唯一想象你想要通过GenericClass <>进行测试的是插件框架场景。
在设计时,C#不允许使用无参数泛型,因为它们在那时基本上不是完整的CLR类型。因此,您必须使用参数声明泛型变量,这就是“is”运算符对于处理对象非常强大的原因。顺便说一句,“是”运算符也不能评估无参数的泛型类型。
“is”运算符将测试整个继承链,包括接口。
因此,给定任何对象的实例,以下方法将起到作用:
bool IsTypeof<T>(object t)
{
return (t is T);
}
这有点多余,但我想我会继续为每个人想象它。
特定
var t = new Test();
以下代码行将返回true:
bool test1 = IsTypeof<GenericInterface<SomeType>>(t);
bool test2 = IsTypeof<GenericClass<SomeType>>(t);
bool test3 = IsTypeof<Test>(t);
另一方面,如果你想要特定于GenericClass的东西,你可以使它更具体,我想,像这样:
bool IsTypeofGenericClass<SomeType>(object t)
{
return (t is GenericClass<SomeType>);
}
然后你会像这样测试:
bool test1 = IsTypeofGenericClass<SomeType>(t);
我研究了一些这些样本,发现在某些情况下它们缺乏。此版本适用于各种泛型:类型,接口和类型定义。
public static bool InheritsOrImplements(this Type child, Type parent)
{
parent = ResolveGenericTypeDefinition(parent);
var currentChild = child.IsGenericType
? child.GetGenericTypeDefinition()
: child;
while (currentChild != typeof (object))
{
if (parent == currentChild || HasAnyInterfaces(parent, currentChild))
return true;
currentChild = currentChild.BaseType != null
&& 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 = childInterface.IsGenericType
? childInterface.GetGenericTypeDefinition()
: childInterface;
return currentInterface == parent;
});
}
private static Type ResolveGenericTypeDefinition(Type parent)
{
var shouldUseGenericType = true;
if (parent.IsGenericType && parent.GetGenericTypeDefinition() != parent)
shouldUseGenericType = false;
if (parent.IsGenericType && shouldUseGenericType)
parent = parent.GetGenericTypeDefinition();
return parent;
}
以下是单元测试:
protected interface IFooInterface
{
}
protected interface IGenericFooInterface<T>
{
}
protected class FooBase
{
}
protected class FooImplementor
: FooBase, IFooInterface
{
}
protected class GenericFooBase
: FooImplementor, IGenericFooInterface<object>
{
}
protected class GenericFooImplementor<T>
: FooImplementor, IGenericFooInterface<T>
{
}
[Test]
public void Should_inherit_or_implement_non_generic_interface()
{
Assert.That(typeof(FooImplementor)
.InheritsOrImplements(typeof(IFooInterface)), Is.True);
}
[Test]
public void Should_inherit_or_implement_generic_interface()
{
Assert.That(typeof(GenericFooBase)
.InheritsOrImplements(typeof(IGenericFooInterface<>)), Is.True);
}
[Test]
public void Should_inherit_or_implement_generic_interface_by_generic_subclass()
{
Assert.That(typeof(GenericFooImplementor<>)
.InheritsOrImplements(typeof(IGenericFooInterface<>)), Is.True);
}
[Test]
public void Should_inherit_or_implement_generic_interface_by_generic_subclass_not_caring_about_generic_type_parameter()
{
Assert.That(new GenericFooImplementor<string>().GetType()
.InheritsOrImplements(typeof(IGenericFooInterface<>)), Is.True);
}
[Test]
public void Should_not_inherit_or_implement_generic_interface_by_generic_subclass_not_caring_about_generic_type_parameter()
{
Assert.That(new GenericFooImplementor<string>().GetType()
.InheritsOrImplements(typeof(IGenericFooInterface<int>)), Is.False);
}
[Test]
public void Should_inherit_or_implement_non_generic_class()
{
Assert.That(typeof(FooImplementor)
.InheritsOrImplements(typeof(FooBase)), Is.True);
}
[Test]
public void Should_inherit_or_implement_any_base_type()
{
Assert.That(typeof(GenericFooImplementor<>)
.InheritsOrImplements(typeof(FooBase)), Is.True);
}
在我看来,这个实现在更多情况下工作(泛型类和接口有或没有启动参数,无论子和参数的数量):
public static class ReflexionExtension
{
public static bool IsSubClassOfGeneric(this Type child, Type parent)
{
if (child == parent)
return false;
if (child.IsSubclassOf(parent))
return true;
var parameters = parent.GetGenericArguments();
var isParameterLessGeneric = !(parameters != null && parameters.Length > 0 &&
((parameters[0].Attributes & TypeAttributes.BeforeFieldInit) == TypeAttributes.BeforeFieldInit));
while (child != null && child != typeof(object))
{
var cur = GetFullTypeDefinition(child);
if (parent == cur || (isParameterLessGeneric && cur.GetInterfaces().Select(i => GetFullTypeDefinition(i)).Contains(GetFullTypeDefinition(parent))))
return true;
else if (!isParameterLessGeneric)
if (GetFullTypeDefinition(parent) == cur && !cur.IsInterface)
{
if (VerifyGenericArguments(GetFullTypeDefinition(parent), cur))
if (VerifyGenericArguments(parent, child))
return true;
}
else
foreach (var item in child.GetInterfaces().Where(i => GetFullTypeDefinition(parent) == GetFullTypeDefinition(i)))
if (VerifyGenericArguments(parent, item))
return true;
child = child.BaseType;
}
return false;
}
private static Type GetFullTypeDefinition(Type type)
{
return type.IsGenericType ? type.GetGenericTypeDefinition() : type;
}
private static bool VerifyGenericArguments(Type parent, Type child)
{
Type[] childArguments = child.GetGenericArguments();
Type[] parentArguments = parent.GetGenericArguments();
if (childArguments.Length == parentArguments.Length)
for (int i = 0; i < childArguments.Length; i++)
if (childArguments[i].Assembly != parentArguments[i].Assembly || childArguments[i].Name != parentArguments[i].Name || childArguments[i].Namespace != parentArguments[i].Namespace)
if (!childArguments[i].IsSubclassOf(parentArguments[i]))
return false;
return true;
}
}
这是我的 70 76个测试用例:
[TestMethod]
public void IsSubClassOfGenericTest()
{
Assert.IsTrue(typeof(ChildGeneric).IsSubClassOfGeneric(typeof(BaseGeneric<>)), " 1");
Assert.IsFalse(typeof(ChildGeneric).IsSubClassOfGeneric(typeof(WrongBaseGeneric<>)), " 2");
Assert.IsTrue(typeof(ChildGeneric).IsSubClassOfGeneric(typeof(IBaseGeneric<>)), " 3");
Assert.IsFalse(typeof(ChildGeneric).IsSubClassOfGeneric(typeof(IWrongBaseGeneric<>)), " 4");
Assert.IsTrue(typeof(IChildGeneric).IsSubClassOfGeneric(typeof(IBaseGeneric<>)), " 5");
Assert.IsFalse(typeof(IWrongBaseGeneric<>).IsSubClassOfGeneric(typeof(ChildGeneric2<>)), " 6");
Assert.IsTrue(typeof(ChildGeneric2<>).IsSubClassOfGeneric(typeof(BaseGeneric<>)), " 7");
Assert.IsTrue(typeof(ChildGeneric2<Class1>).IsSubClassOfGeneric(typeof(BaseGeneric<>)), " 8");
Assert.IsTrue(typeof(ChildGeneric).IsSubClassOfGeneric(typeof(BaseGeneric<Class1>)), " 9");
Assert.IsFalse(typeof(ChildGeneric).IsSubClassOfGeneric(typeof(WrongBaseGeneric<Class1>)), "10");
Assert.IsTrue(typeof(ChildGeneric).IsSubClassOfGeneric(typeof(IBaseGeneric<Class1>)), "11");
Assert.IsFalse(typeof(ChildGeneric).IsSubClassOfGeneric(typeof(IWrongBaseGeneric<Class1>)), "12");
Assert.IsTrue(typeof(IChildGeneric).IsSubClassOfGeneric(typeof(IBaseGeneric<Class1>)), "13");
Assert.IsFalse(typeof(BaseGeneric<Class1>).IsSubClassOfGeneric(typeof(ChildGeneric2<Class1>)), "14");
Assert.IsTrue(typeof(ChildGeneric2<Class1>).IsSubClassOfGeneric(typeof(BaseGeneric<Class1>)), "15");
Assert.IsFalse(typeof(ChildGeneric).IsSubClassOfGeneric(typeof(ChildGeneric)), "16");
Assert.IsFalse(typeof(IChildGeneric).IsSubClassOfGeneric(typeof(IChildGeneric)), "17");
Assert.IsFalse(typeof(IBaseGeneric<>).IsSubClassOfGeneric(typeof(IChildGeneric2<>)), "18");
Assert.IsTrue(typeof(IChildGeneric2<>).IsSubClassOfGeneric(typeof(IBaseGeneric<>)), "19");
Assert.IsTrue(typeof(IChildGeneric2<Class1>).IsSubClassOfGeneric(typeof(IBaseGeneric<>)), "20");
Assert.IsFalse(typeof(IBaseGeneric<Class1>).IsSubClassOfGeneric(typeof(IChildGeneric2<Class1>)), "21");
Assert.IsTrue(typeof(IChildGeneric2<Class1>).IsSubClassOfGeneric(typeof(IBaseGeneric<Class1>)), "22");
Assert.IsFalse(typeof(IBaseGeneric<Class1>).IsSubClassOfGeneric(typeof(BaseGeneric<Class1>)), "23");
Assert.IsTrue(typeof(BaseGeneric<Class1>).IsSubClassOfGeneric(typeof(IBaseGeneric<Class1>)), "24");
Assert.IsFalse(typeof(IBaseGeneric<>).IsSubClassOfGeneric(typeof(BaseGeneric<>)), "25");
Assert.IsTrue(typeof(BaseGeneric<>).IsSubClassOfGeneric(typeof(IBaseGeneric<>)), "26");
Assert.IsTrue(typeof(BaseGeneric<Class1>).IsSubClassOfGeneric(typeof(IBaseGeneric<>)), "27");
Assert.IsFalse(typeof(IBaseGeneric<Class1>).IsSubClassOfGeneric(typeof(IBaseGeneric<Class1>)), "28");
Assert.IsTrue(typeof(BaseGeneric2<Class1>).IsSubClassOfGeneric(typeof(IBaseGeneric<Class1>)), "29");
Assert.IsFalse(typeof(IBaseGeneric<>).IsSubClassOfGeneric(typeof(BaseGeneric2<>)), "30");
Assert.IsTrue(typeof(BaseGeneric2<>).IsSubClassOfGeneric(typeof(IBaseGeneric<>)), "31");
Assert.IsTrue(typeof(BaseGeneric2<Class1>).IsSubClassOfGeneric(typeof(IBaseGeneric<>)), "32");
Assert.IsTrue(typeof(ChildGenericA).IsSubClassOfGeneric(typeof(BaseGenericA<,>)), "33");
Assert.IsFalse(typeof(ChildGenericA).IsSubClassOfGeneric(typeof(WrongBaseGenericA<,>)), "34");
Assert.IsTrue(typeof(ChildGenericA).IsSubClassOfGeneric(typeof(IBaseGenericA<,>)), "35");
Assert.IsFalse(typeof(ChildGenericA).IsSubClassOfGeneric(typeof(IWrongBaseGenericA<,>)), "36");
Assert.IsTrue(typeof(IChildGenericA).IsSubClassOfGeneric(typeof(IBaseGenericA<,>)), "37");
Assert.IsFalse(typeof(IWrongBaseGenericA<,>).IsSubClassOfGeneric(typeof(ChildGenericA2<,>)), "38");
Assert.IsTrue(typeof(ChildGenericA2<,>).IsSubClassOfGeneric(typeof(BaseGenericA<,>)), "39");
Assert.IsTrue(typeof(ChildGenericA2<ClassA, ClassB>).IsSubClassOfGeneric(typeof(BaseGenericA<,>)), "40");
Assert.IsTrue(typeof(ChildGenericA).IsSubClassOfGeneric(typeof(BaseGenericA<ClassA, ClassB>)), "41");
Assert.IsFalse(typeof(ChildGenericA).IsSubClassOfGeneric(typeof(WrongBaseGenericA<ClassA, ClassB>)), "42");
Assert.IsTrue(typeof(ChildGenericA).IsSubClassOfGeneric(typeof(IBaseGenericA<ClassA, ClassB>)), "43");
Assert.IsFalse(typeof(ChildGenericA).IsSubClassOfGeneric(typeof(IWrongBaseGenericA<ClassA, ClassB>)), "44");
Assert.IsTrue(typeof(IChildGenericA).IsSubClassOfGeneric(typeof(IBaseGenericA<ClassA, ClassB>)), "45");
Assert.IsFalse(typeof(BaseGenericA<ClassA, ClassB>).IsSubClassOfGeneric(typeof(ChildGenericA2<ClassA, ClassB>)), "46");
Assert.IsTrue(typeof(ChildGenericA2<ClassA, ClassB>).IsSubClassOfGeneric(typeof(BaseGenericA<ClassA, ClassB>)), "47");
Assert.IsFalse(typeof(ChildGenericA).IsSubClassOfGeneric(typeof(ChildGenericA)), "48");
Assert.IsFalse(typeof(IChildGenericA).IsSubClassOfGeneric(typeof(IChildGenericA)), "49");
Assert.IsFalse(typeof(IBaseGenericA<,>).IsSubClassOfGeneric(typeof(IChildGenericA2<,>)), "50");
Assert.IsTrue(typeof(IChildGenericA2<,>).IsSubClassOfGeneric(typeof(IBaseGenericA<,>)), "51");
Assert.IsTrue(typeof(IChildGenericA2<ClassA, ClassB>).IsSubClassOfGeneric(typeof(IBaseGenericA<,>)), "52");
Assert.IsFalse(typeof(IBaseGenericA<ClassA, ClassB>).IsSubClassOfGeneric(typeof(IChildGenericA2<ClassA, ClassB>)), "53");
Assert.IsTrue(typeof(IChildGenericA2<ClassA, ClassB>).IsSubClassOfGeneric(typeof(IBaseGenericA<ClassA, ClassB>)), "54");
Assert.IsFalse(typeof(IBaseGenericA<ClassA, ClassB>).IsSubClassOfGeneric(typeof(BaseGenericA<ClassA, ClassB>)), "55");
Assert.IsTrue(typeof(BaseGenericA<ClassA, ClassB>).IsSubClassOfGeneric(typeof(IBaseGenericA<ClassA, ClassB>)), "56");
Assert.IsFalse(typeof(IBaseGenericA<,>).IsSubClassOfGeneric(typeof(BaseGenericA<,>)), "57");
Assert.IsTrue(typeof(BaseGenericA<,>).IsSubClassOfGeneric(typeof(IBaseGenericA<,>)), "58");
Assert.IsTrue(typeof(BaseGenericA<ClassA, ClassB>).IsSubClassOfGeneric(typeof(IBaseGenericA<,>)), "59");
Assert.IsFalse(typeof(IBaseGenericA<ClassA, ClassB>).IsSubClassOfGeneric(typeof(IBaseGenericA<ClassA, ClassB>)), "60");
Assert.IsTrue(typeof(BaseGenericA2<ClassA, ClassB>).IsSubClassOfGeneric(typeof(IBaseGenericA<ClassA, ClassB>)), "61");
Assert.IsFalse(typeof(IBaseGenericA<,>).IsSubClassOfGeneric(typeof(BaseGenericA2<,>)), "62");
Assert.IsTrue(typeof(BaseGenericA2<,>).IsSubClassOfGeneric(typeof(IBaseGenericA<,>)), "63");
Assert.IsTrue(typeof(BaseGenericA2<ClassA, ClassB>).IsSubClassOfGeneric(typeof(IBaseGenericA<,>)), "64");
Assert.IsFalse(typeof(BaseGenericA2<ClassB, ClassA>).IsSubClassOfGeneric(typeof(IBaseGenericA<ClassA, ClassB>)), "65");
Assert.IsFalse(typeof(BaseGenericA<ClassB, ClassA>).IsSubClassOfGeneric(typeof(ChildGenericA2<ClassA, ClassB>)), "66");
Assert.IsFalse(typeof(BaseGenericA2<ClassB, ClassA>).IsSubClassOfGeneric(typeof(BaseGenericA<ClassA, ClassB>)), "67");
Assert.IsTrue(typeof(ChildGenericA3<ClassA, ClassB>).IsSubClassOfGeneric(typeof(BaseGenericB<ClassA, ClassB, ClassC>)), "68");
Assert.IsTrue(typeof(ChildGenericA4<ClassA, ClassB>).IsSubClassOfGeneric(typeof(IBaseGenericB<ClassA, ClassB, ClassC>)), "69");
Assert.IsFalse(typeof(ChildGenericA3<ClassB, ClassA>).IsSubClassOfGeneric(typeof(BaseGenericB<ClassA, ClassB, ClassC>)), "68-2");
Assert.IsTrue(typeof(ChildGenericA3<ClassA, ClassB2>).IsSubClassOfGeneric(typeof(BaseGenericB<ClassA, ClassB, ClassC>)), "68-3");
Assert.IsFalse(typeof(ChildGenericA3<ClassB2, ClassA>).IsSubClassOfGeneric(typeof(BaseGenericB<ClassA, ClassB, ClassC>)), "68-4");
Assert.IsFalse(typeof(ChildGenericA4<ClassB, ClassA>).IsSubClassOfGeneric(typeof(IBaseGenericB<ClassA, ClassB, ClassC>)), "69-2");
Assert.IsTrue(typeof(ChildGenericA4<ClassA, ClassB2>).IsSubClassOfGeneric(typeof(IBaseGenericB<ClassA, ClassB, ClassC>)), "69-3");
Assert.IsFalse(typeof(ChildGenericA4<ClassB2, ClassA>).IsSubClassOfGeneric(typeof(IBaseGenericB<ClassA, ClassB, ClassC>)), "69-4");
Assert.IsFalse(typeof(bool).IsSubClassOfGeneric(typeof(IBaseGenericB<ClassA, ClassB, ClassC>)), "70");
}
用于测试的类和接口:
public class Class1 { }
public class BaseGeneric<T> : IBaseGeneric<T> { }
public class BaseGeneric2<T> : IBaseGeneric<T>, IInterfaceBidon { }
public interface IBaseGeneric<T> { }
public class ChildGeneric : BaseGeneric<Class1> { }
public interface IChildGeneric : IBaseGeneric<Class1> { }
public class ChildGeneric2<Class1> : BaseGeneric<Class1> { }
public interface IChildGeneric2<Class1> : IBaseGeneric<Class1> { }
public class WrongBaseGeneric<T> { }
public interface IWrongBaseGeneric<T> { }
public interface IInterfaceBidon { }
public class ClassA { }
public class ClassB { }
public class ClassC { }
public class ClassB2 : ClassB { }
public class BaseGenericA<T, U> : IBaseGenericA<T, U> { }
public class BaseGenericB<T, U, V> { }
public interface IBaseGenericB<ClassA, ClassB, ClassC> { }
public class BaseGenericA2<T, U> : IBaseGenericA<T, U>, IInterfaceBidonA { }
public interface IBaseGenericA<T, U> { }
public class ChildGenericA : BaseGenericA<ClassA, ClassB> { }
public interface IChildGenericA : IBaseGenericA<ClassA, ClassB> { }
public class ChildGenericA2<ClassA, ClassB> : BaseGenericA<ClassA, ClassB> { }
public class ChildGenericA3<ClassA, ClassB> : BaseGenericB<ClassA, ClassB, ClassC> { }
public class ChildGenericA4<ClassA, ClassB> : IBaseGenericB<ClassA, ClassB, ClassC> { }
public interface IChildGenericA2<ClassA, ClassB> : IBaseGenericA<ClassA, ClassB> { }
public class WrongBaseGenericA<T, U> { }
public interface IWrongBaseGenericA<T, U> { }
public interface IInterfaceBidonA { }
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);
}
它可能有点矫枉过正,但我使用如下的扩展方法。他们检查接口和子类。它还可以返回具有指定泛型定义的类型。
例如。对于问题中的示例,它可以测试通用接口以及泛型类。返回的类型可以与GetGenericArguments
一起使用,以确定泛型参数类型是“SomeType”。
/// <summary>
/// Checks whether this type has the specified definition in its ancestry.
/// </summary>
public static bool HasGenericDefinition(this Type type, Type definition)
{
return GetTypeWithGenericDefinition(type, definition) != null;
}
/// <summary>
/// Returns the actual type implementing the specified definition from the
/// ancestry of the type, if available. Else, null.
/// </summary>
public static Type GetTypeWithGenericDefinition(this Type type, Type definition)
{
if (type == null)
throw new ArgumentNullException("type");
if (definition == null)
throw new ArgumentNullException("definition");
if (!definition.IsGenericTypeDefinition)
throw new ArgumentException(
"The definition needs to be a GenericTypeDefinition", "definition");
if (definition.IsInterface)
foreach (var interfaceType in type.GetInterfaces())
if (interfaceType.IsGenericType
&& interfaceType.GetGenericTypeDefinition() == definition)
return interfaceType;
for (Type t = type; t != null; t = t.BaseType)
if (t.IsGenericType && t.GetGenericTypeDefinition() == definition)
return t;
return null;
}
基于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>)));
}
这可以通过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<,>));