C# 将IsAssignableFrom与';打开';泛型
使用反射,我试图找到从给定基类继承的类型集。没有花很长时间就搞清楚了简单类型,但当涉及到泛型时,我被难住了 对于这段代码,第一个IsAssignableFrom返回true,但第二个返回false。然而,最后的作业编写得很好C# 将IsAssignableFrom与';打开';泛型,c#,generics,reflection,types,C#,Generics,Reflection,Types,使用反射,我试图找到从给定基类继承的类型集。没有花很长时间就搞清楚了简单类型,但当涉及到泛型时,我被难住了 对于这段代码,第一个IsAssignableFrom返回true,但第二个返回false。然而,最后的作业编写得很好 class class1 { } class class2 : class1 { } class generic1<T> { } class generic2<T> : generic1<T> { } class Program {
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>();
}
}
class1{}
类别2:class1{}
类generic1{}
类generic2:generic1{}
班级计划
{
静态void Main(字符串[]参数)
{
c1类=类型(类别1);
c2类=类型(类别2);
WriteLine(“c1.IsAssignableFrom(c2):{0}”,c1.IsAssignableFrom(c2));
g1型=类型(一般1);
g2型=类型(一般2);
WriteLine(“g1.IsAssignableFrom(g2):{0}”,g1.IsAssignableFrom(g2));
generic1 cc=新的generic2();
}
}
那么,如何在运行时确定一个泛型类型定义是否派生自另一个泛型类型定义呢?您需要比较包含的类型。见: 换句话说,我认为您需要检查泛型类所包含的类型是否可赋值,而不是泛型类本身。来自:
(如果你喜欢这个答案,请将链接的答案向上投票,因为代码不是我的。)你发布的确切代码不会返回令人惊讶的结果 上面写着“假”:
Type g1=typeof(generic1);
g2型=类型(一般2);
WriteLine(“g1.IsAssignableFrom(g2):{0}”,g1.IsAssignableFrom(g2));
这是“真的”:
Type g1=typeof(generic1);
g2型=类型(一般2);
WriteLine(“g1.IsAssignableFrom(g2):{0}”,g1.IsAssignableFrom(g2));
区别在于开放泛型类型不能有实例,因此一个实例不能“分配”给另一个实例
从:
返回true
如果c
和当前
类型
表示相同的类型,或者
当前的类型
位于
c
的继承层次结构,或者如果
当前的类型
是一个接口
c
实现,或者如果c
是
泛型类型参数和当前
类型
表示
c
的约束条件<代码>错误如果没有
这些条件为真,或者如果c
是null
在这种情况下,这些条件显然都不成立。还有一个额外的注意事项:
不支持泛型类型定义
可从封闭结构中赋值的
类型。也就是说,您不能分配
封闭构造型
MyGenericList
(MyGenericList(在Visual Basic中为整数)
)到
类型为MyGenericList
的变量
在以下情况下,使用Konrad Rudolph提供的方法可能是错误的,例如:IsAssignableToGenericType(typeof(A),typeof(A));//返回错误 我想这里有一个更好的答案
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;
}
有关测试用例的详细信息,请参见
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{}
}
使用系统;
/**
*Sam Sha-yCoder.com
*
* */
名称空间Test2
{
类主类
{
公共静态void Main(字符串[]args)
{
字符串a=“ycoder”;
Console.WriteLine(一个是对象);
A aa=新的A();
//Console.WriteLine(aa是一个);//不能这样写代码
typeof(A).IsAssignableFrom(aa.GetType());//返回false
Trace(typeof(object).IsAssignableFrom(typeof(string));//true
Trace(typeof(A).IsAssignableFrom(typeof(A));//false
AAA=新的AAA();
跟踪(“使用IsTypeOf:”);
跟踪(IsTypeOf(aaa,typeof(A));
跟踪(IsTypeOf(aaa,typeof(AA));
跟踪(IsTypeOf(aaa,typeof(aaa));
跟踪(“使用来自stackoverflow的IsAssignableFrom-不正确:”;
跟踪(IsAssignableFrom(typeof(A),typeof(A));//错误
痕迹(可识别自(AA型,A型));
跟踪(可从(类型(AAA),类型(A));
跟踪(“使用IsAssignableToGenericType:”);
痕量(IsAssignableToGenericType(A型,A型));
痕量(IsAssignableToGenericType(AA型,A型));
痕量(IsAssignableToGenericType(类型为(AAA),类型为(A));
}
静态无效跟踪(对象日志){
控制台写入线(日志);
}
公共静态bool IsTypeOf(对象o,类型baseType)
{
if(o==null | | baseType==null)
{
返回false;
}
bool result=baseType.IsInstanceOfType(o);
如果(结果)
{
返回结果;
}
返回IsAssignableFrom(o.GetType(),baseType);
}
公共静态bool IsAssignableFrom(类型extendType,类型baseType)
{
而(!baseType.IsAssignableFrom(extendType))
{
if(extendType.Equals(typeof(object)))
{
返回false;
}
if(extendType.IsGenericType&&!extendType.IsGenericTypeDefinition)
{
extendType=extendType.GetGenericTypeDefinition();
}
其他的
{
extendType=extendType.BaseType;
}
}
返回true;
}
//来自stackoverflow-不够好
公共静态bool IsAssignableToGenericType(类型givenType,类型genericType){
var interfaceTypes=givenType.GetInterfaces();
foreach(在interfaceTypes中变量it)
if(it.IsGenericType)
如果(it.GetGenericTypeDefinition()==genericType)返回true;
类型baseType=givenType.baseType;
if(baseType==null)返回false;
返回baseType.IsGenericType&&
baseType.GetGenericTypeDefinition()==genericType
Type g1 = typeof(generic1<class1>);
Type g2 = typeof(generic2<class1>);
Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2));
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;
}
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{}
}
public class Signal<T>{
protected string Id {get; set;} //This must be here, I use a property because MemberInfo is returned in an array via GetMember() reflection function
//Some Data and Logic And stuff that involves T
}
public class OnClick : Signal<string>{}
Type type = GetTypeWhomISuspectMightBeAGenericSignal();
PropertyInfo secretProperty = type.GetProperty("Id", BindingFlags.NonPublic | BindingFlags.Instance);
Type SpecificGenericType = secretProperty.DeclaringType; //This is the trick
bool IsMyTypeInheriting = SpecificGenericType.IsGenericType && SpecificGenericType.GetGenericTypeDefinition() == typeof(Signal<>); //This way we are getting the genericTypeDefinition and comparing it to any other genericTypeDefinition of the same argument length.