Type类方法的使用-判断某个类是否是某个接口的派生类

来源:互联网 发布:mt4编程入门 编辑:程序博客网 时间:2024/05/16 23:42

     近期系统架构为以后数据集成做了一次调整,在更新完系统架构,调整Examples项目的时候发现,原系统框架中对于DTO类型的判断使用的是字符串进行比较,以前的写法如下:

typeDTO.BaseType.FullName.Contains("DTOBase")

    先说一下这一段代码的问题,typeDTO是传入的DTO类型,判断时使用的是其父类的类型的全类名,是否包含DTOBase,如果项目中直接继承框架中的DTOBase,这段代码可以正常判断,如果项目中在DTOBase的基础上再加一层封装,那这段代码就无法正确判断typeDTO是否是DTOBase的派生类了。

    另外,本次系统架构调整实体和聚合根的DTO分别​继承DTOEntityBase和DTOAggregateRootBase,但他们都实现了IDTO的泛型接口。我的想法是直接判断传入的DTO是否派生自IDTO,但由于IDTO是泛型接口,我不知道该如何判断。

    问过杨总之后,杨总给我讲了一下泛型类的全名格式是这样的“IDTO~1”,~1表示包含一个泛型参数。如果使用IDTO~1来判断的话可以解决泛型接口判断的问题,但还是存在我上面描述的二次封装的问题。杨总又建议我们使用Type.MakeGenericType 方法,在运行时通过反射构造泛型类型的实例。代码如下:

Type _typeEntity = _typeDTO.BaseType.GenericTypeArguments[0];
Type genericSourceType = typeof(IDTO<>).MakeGenericType(new[] { _typeEntity });

在这里详细说明一下,第一行代码是获取泛型参数的实例类型。用于第二行构造泛型类型。构造完成之后,我们就可以使用Type.IsAssignableFrom 方法判断了。代码如下:

if (!genericSourceType.IsAssignableFrom(typeDTO))
{
     throw new ArgumentException("不是有效的数据传输对象!", "typeDTO");
}

看到这的时候大家可能想到了Type.IsSubclassOf  方法,Type.IsSubclassOf  方法和Type.IsSubclassOf  方法的区别在于,前者只能用于判断类的继承关系。

举个例子,看一下这两种方法对于类继承及接口实现的判断,接口及其实现类及其实现类的子类定义如下:

interface I { // TODO }
class A : I { // TODO }
class B : A { // TODO }

IsSubclassOf和IsAssignableFrom的返回值为:

typeof(A).isAssignableFrom(typeof(I)); // false
typeof(A).isSubClassOf(typeof(I)); // false
 
typeof(I).isAssignableFrom(typeof(A)); // true
typeof(I).isAssignableFrom(typeof(B)); // true
typeof(B).isSubClassOf(typeof(I)); // false
 
typeof(A).isAssignableFrom(typeof(A)); // true
typeof(A).isSubClassof(typeof(A)); // false
 
typeof(A).isAssignableFrom(typeof(B)); // true
typeof(A).isSubClassof(typeof(B)); // false
 
typeof(B).isAssignableFrom(typeof(A)); // false
typeof(B).isSubClassof(typeof(A)); // true

0 0