使用IsAssignableFrom和'open'genericstypes

使用reflection,我试图find从给定的基类inheritance的types的集合。 找出简单的types并不需要太长的时间,但是当涉及到非专利types的时候,我却难以理解了。

对于这段代码,第一个IsAssignableFrom返回true,但是第二个返回false。 然而,最后的任务编译得很好。

class class1 { } class class2 : class1 { } class generic1<T> { } class generic2<T> : generic1<T> { } class Program { static void Main(string[] args) { Type c1 = typeof(class1); Type c2 = typeof(class2); Console.WriteLine("c1.IsAssignableFrom(c2): {0}", c1.IsAssignableFrom(c2)); Type g1 = typeof(generic1<>); Type g2 = typeof(generic2<>); Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2)); generic1<class1> cc = new generic2<class1>(); } } 

那么如何在运行时确定一个genericstypes定义是否从另一个generics定义派生?

从答案到另一个问题 :

 public static bool IsAssignableToGenericType(Type givenType, Type genericType) { var interfaceTypes = givenType.GetInterfaces(); foreach (var it in interfaceTypes) { if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType) return true; } if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) return true; Type baseType = givenType.BaseType; if (baseType == null) return false; return IsAssignableToGenericType(baseType, genericType); } 

(如果你喜欢答案,请upvote链接的答案,因为代码不是我的。)

您发布的确切代码不会返回令人惊讶的结果。

这说“错误”:

 Type g1 = typeof(generic1<>); Type g2 = typeof(generic2<>); Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2)); 

这说“真”:

 Type g1 = typeof(generic1<class1>); Type g2 = typeof(generic2<class1>); Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2)); 

不同的是,开放的genericstypes不能有实例,所以一个不能“赋值”到另一个。

从文档 :

如果c和当前的Type代表相同的types,或者当前的Type位于c的inheritance层次结构中,或者当前的Typec实现的接口,或者c是genericstypes参数,并且当前的Type代表c的约束之一。 如果这些条件都不成立,或者cnull ,则返回null

在这种情况下,显然这些条件都不是真的。 还有一个额外的说明:

genericstypes定义不能从封闭的构造types分配。 也就是说,您不能将封闭的构造typesMyGenericList<int> (Visual Basic中的MyGenericList(Of Integer) )分配给MyGenericList<T>types的variables。

在下面的情况下,使用Konrad Rudolph提供的方法可能是错误的,如:IsAssignableToGenericType(typeof(A),typeof(A <>)); //返回false

我想这是一个更好的答案

 public static bool IsAssignableFrom(Type extendType, Type baseType) { while (!baseType.IsAssignableFrom(extendType)) { if (extendType.Equals(typeof(object))) { return false; } if (extendType.IsGenericType && !extendType.IsGenericTypeDefinition) { extendType = extendType.GetGenericTypeDefinition(); } else { extendType = extendType.BaseType; } } return true; } 

testing用例,请参阅使用C#generics的IsAssignableFrom来获取详细信息

 using System; /** * Sam Sha - yCoder.com * * */ namespace Test2 { class MainClass { public static void Main (string[] args) { string a = "ycoder"; Console.WriteLine(a is object); A aa = new A(); //Console.WriteLine(aa is A<>);//con't write code like this typeof(A<>).IsAssignableFrom(aa.GetType());//return false Trace(typeof(object).IsAssignableFrom(typeof(string)));//true Trace(typeof(A<>).IsAssignableFrom(typeof(A)));//false AAA aaa = new AAA(); Trace("Use IsTypeOf:"); Trace(IsTypeOf(aaa, typeof(A<>))); Trace(IsTypeOf(aaa, typeof(AA))); Trace(IsTypeOf(aaa, typeof(AAA<>))); Trace("Use IsAssignableFrom from stackoverflow - not right:"); Trace(IsAssignableFrom(typeof(A), typeof(A<>))); // error Trace(IsAssignableFrom(typeof(AA), typeof(A<>))); Trace(IsAssignableFrom(typeof(AAA), typeof(A<>))); Trace("Use IsAssignableToGenericType:"); Trace(IsAssignableToGenericType(typeof(A), typeof(A<>))); Trace(IsAssignableToGenericType(typeof(AA), typeof(A<>))); Trace(IsAssignableToGenericType(typeof(AAA), typeof(A<>))); } static void Trace(object log){ Console.WriteLine(log); } public static bool IsTypeOf(Object o, Type baseType) { if (o == null || baseType == null) { return false; } bool result = baseType.IsInstanceOfType(o); if (result) { return result; } return IsAssignableFrom(o.GetType(), baseType); } public static bool IsAssignableFrom(Type extendType, Type baseType) { while (!baseType.IsAssignableFrom(extendType)) { if (extendType.Equals(typeof(object))) { return false; } if (extendType.IsGenericType && !extendType.IsGenericTypeDefinition) { extendType = extendType.GetGenericTypeDefinition(); } else { extendType = extendType.BaseType; } } return true; } //from stackoverflow - not good enough public static bool IsAssignableToGenericType(Type givenType, Type genericType) { var interfaceTypes = givenType.GetInterfaces(); foreach (var it in interfaceTypes) if (it.IsGenericType) if (it.GetGenericTypeDefinition() == genericType) return true; Type baseType = givenType.BaseType; if (baseType == null) return false; return baseType.IsGenericType && baseType.GetGenericTypeDefinition() == genericType || IsAssignableToGenericType(baseType, genericType); } } class A{} class AA : A{} class AAA : AA{} } 

你需要比较包含的types。 请参阅: 如何从generics类或方法的成员获取T的types?

换句话说,我认为你需要检查generics类包含的types是否可赋值,而不是generics类本身。