我有一个泛型类在我的项目与派生类。
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<>))
不管用。
当前回答
在我看来,这个实现在更多的情况下工作(泛型类和接口有或没有初始参数,不管子和参数的数量):
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;
}
}
以下是我的7076个测试用例:
[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 { }
其他回答
你可以试试这个扩展
public static bool IsSubClassOfGenericClass(this Type type, Type genericClass,Type t)
{
return type.IsSubclassOf(genericClass.MakeGenericType(new[] { t }));
}
Type _type = myclass.GetType();
PropertyInfo[] _propertyInfos = _type.GetProperties();
Boolean _test = _propertyInfos[0].PropertyType.GetGenericTypeDefinition()
== typeof(List<>);
贾里德帕尔
这并不为我工作,如果我通过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;
}
这个游戏已经晚了…我对JarodPar的答案也有另一种排列。
下面是Type. issubclassof (Type),由reflector提供:
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的一个扩展方法。类型-我这样做是为了故意将“thisType”类型限制为具体类型,因为我的直接用法是对类型对象的LINQ查询“where”谓词。我相信所有聪明的人都可以把它归结为一个有效的,通用的静态方法,如果你需要:)代码做了一些事情,答案的代码没有
open's it up to to general "extension" - i'm considering inheritance (think classes) as well as implementation (interfaces); method and parameter names are changed to better reflect this input null-validation (meah) input of same type (a class cannot extend itself) short-circuit execution if Type in question is an interface; because GetInterfaces() returns all implemented interfaces (even ones implemented in super-classes), you can simply loop through that collection not having to climb the inheritance tree
其余部分基本上与JaredPar的代码相同
下面是我创建的一个小方法,用于检查对象是否派生于特定类型。对我来说太棒了!
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);
}