专栏首页明丰随笔浅谈.Net反射 5

浅谈.Net反射 5

反射是动态操作元数据的能力,从程序集-模块-类型-字段-属性-方法-参数等,反射可以动态操作这些部分,在编译时不确定,在运行中动态确定,并进行有效控制。

今天本文主要聊聊Type类,反射的核心是Type类,这个类封装了关于类型的元数据,也是进行反射的入口。

当获得了类型的Type对象后,就可以根据Type提供的属性和方法获取这个类型的一切信息,包括构造函数、字段、属性、事件、方法、参数等。

获取已加载程序集中类型的Type对象,一般来说有以下三种方法:

1.使用Type类提供的静态方法GetType()

GetType方法接受字符串形式的类型名称

Type t = Type.GetType("System.IO.Stream");

2.使用typeof操作符

ypeof操作符来完成这一操作,有点像泛型,Stream就好像一个类型参数一样,传递到typeof操作符中。

Type t = typeof(System.IO.Stream);

3.通过类型实例获得Type对象

在类型实例上调用继承自System.Object的GetType()方法来获得Type对象,使用这种方法时应当注意,返回的Type对象本身不包含关于特定对象的特定信息。

Stream memoryStream = new MemoryStream();
memoryStream.WriteByte(1);
Type t = memoryStream.GetType();

这里的t并不知道memoryStream实例对象里面有哪些信息。

Type类型及System.Reflection命名空间的组织结构

假设我们顺利的拿到了Type对象t:

MemoryStream memoryStream = new MemoryStream();
memoryStream.WriteByte(1);
Type t = memoryStream.GetType();

现在通过t,我们可以获得哪些信息?

1. memoryStream对象的类型的基本信息

通过上图,可以获得:

memoryStream对象的类型,

类型的命名空间,

类型的基类,

在.NET运行库中的映射类型,

是public、private,还是protected,

是值类型还是引用类型,

是不是基元类型,

是枚举、类、数组,还是接口,

2. memoryStream对象的类型的成员信息

除了类型本身的信息以外,还要进一步知道它的成员信息:

a. 包含哪些字段,字段名称、类型、可访问性。

b. 包含哪些属性,属性名称、类型、可访问性。

c. 包含哪些构造函数,构造函数的名称,构造函数的参数个数、参数类型、参数名称

d. 包含哪些方法,方法的名称,方法的返回值类型,方法的参数个数、参数类型、参数名称

e. 包含哪些事件,事件的名称。

f. 实现了哪些接口

g. 可以逐级深入的,比如可以再次获得memoryStream对象的类型的属性的类型的Type信息,然后再次深入下去。

观察上面的列举,先就第一条来说,获取类型都有哪些字段,以及这些字段的信息。字段的信息包括:字段的类型、字段的名称、字段的可访问性(public、private)、字段是否为const、字段是否为readonly,等等,所有这些关于字段的信息也应该抽象为一个类型。

如同上一节所讲到的,System.Reflection命名空间下提供了FieldInfo类型,它封装了关于字段的所有信息。

一样的思路,FCL还给属性,构造器,方法,事件,参数定义了XXXInfo类型:

TypeInfo类型,封装了类的信息;

PropertyInfo类型,封装了类型的属性信息;

ConstructorInfo类型,封装了类型的构造函数信息;

MethodInfo类型,封装了类型的方法信息;

EventInfo类型,封装了类型的事件信息;

ParameterInfo类型,封装了方法和构造函数的参数信息;

最后,注意到Type类型,以及所有以Info结尾的类型均继承自System.Reflection.MemberInfo类型,MemberInfo类型提供了获取类型基础信息的能力。

浏览Type类型的成员,会发现它的属性和方法可以大致分为以下几组:

a. IsXXXX,比如IsAbstract、IsClass,这组属性返回bool类型,用于说明类型是否具备某些特性。

b. GetXXXX(),比如GetField(),返回FieldInfo,这组方法用于获取某一特定成员的信息。

c. GetXXXXs(),比如GetFields(),返回FieldInfo[],这组方法用户获取某些成员信息。

d. 其他的一些属性和方法

由于MemberInfo是一个抽象基类,在获得一个MemberInfo对象后,并不知道它的实际类型是PropertyInfo还是FieldInfo。因此,需要提供方法进行判断,在System.Reflection命名空间中,会遇到很多的位标记,这里先介绍一个位标记(用[Flags]特性标记的枚举,称为位标记),MemberTypes,它用于标记成员类型,取值如下:

[Flags]
public enum MemberTypes {
  Constructor = 1, // 该成员是一个构造函数
  Event = 2, // 该成员是一个事件
  Field = 4, // 该成员是一个字段
  Method = 8, // 该成员是一个方法
  Property = 16, // 该成员是一个属性
  TypeInfo = 32, // 该成员是一种类型
  Custom = 64, // 自定义成员类型
  NestedType = 128, // 该成员是一个嵌套类型
  All = 191, // 指定所有成员类型。
}

本文回顾:

获取某类型的Type对象

某类型的基本信息

某类型的成员信息

MemberInfo类型

Type类型

TypeInfo类型

PropertyInfo类型

ConstructorInfo类型

MethodInfo类型

EventInfo类型

ParameterInfo类型

MemberTypes枚举

本文分享自微信公众号 - 明丰随笔(liumingfengwx2),作者:刘明丰

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-07-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 浅谈.Net反射 3

    在.NET中,提供了System.Type类和System.Reflection命名空间实现了反射的功能。

    小蜜蜂
  • 浅谈.Net反射 10

    在前面几篇当中,先了解了反射,然后利用反射查看了类型信息,并学习了如何创建自定义特性,以及如何利用反射来获取特性对象。

    小蜜蜂
  • 浅谈.Net反射 2

    C#代码在经过编译之后会得到二进制格式的程序集,程序集一般是一个.dll或.exe后缀的文件。

    小蜜蜂
  • 类型即正义:TypeScript 从入门到实践(二):函数、交叉/联合类型与类型守卫

    了解了基础的 TS 类型,接口之后,我们开始了解如何给更加复杂的结构注解类型,这就是我们这节里面要引出的函数,进而我们讲解如何对类型进行运算:交叉类型和联合类型...

    一只图雀
  • Golang学习笔记 数据类型和变量

    数据类型 先来介绍一下Golang的数据类型。 布尔型 bool类型代表逻辑值,有真值true和假值false两种取值。 整数类型 整数类型有如下几种,这些整数...

    乐百川
  • go 参数传递

    http://stor.51cto.com/art/201712/559955.htm go 中都是值传递的,即使是map、切片这些。 只不过类型分为:

    平凡的学生族
  • 浅谈.Net反射 3

    在.NET中,提供了System.Type类和System.Reflection命名空间实现了反射的功能。

    小蜜蜂
  • int 和 Integer 有什么区别?

    int 是 java 的原始数据类型,Integer 是 java 为 int 提供的封装类。

    MickyInvQ
  • Go数据结构与算法之内置类型

    每一种编程语言都会内置几种基本的数据结构。例如:Python的List、Dict、Set等。基本数据类型可以大概分为两类:

    宇宙之一粟
  • 深入 TypeScript 中的子类型,进阶 Vue3 源码前必须搞懂的。

    TypeScript 中有很多地方涉及到子类型 subtype、父类型 supertype 的概念,如果搞不清这些概念,那么很可能被报错搞的无从下手,或者在写一...

    ssh1995

扫码关注云+社区

领取腾讯云代金券