一、元数据和反射

  1.1 定义

  大多数程序都要处理数据,包括读、写、操作和显示数据。然而,对于某些程序来说,它们操作的不是数字、文本或图形,而是程序和程序类型本身的信息。

    ● 有关程序及其类型的数据被称为元数据(metadata),它们保存在程序的程序集中

    ● 程序在运行时,可以查看其他程序集或其本身的元数据。一个运行的程序查看本身的元数据和其他程序的元数据的行为叫做反射(reflection) 

  反射提供了封装程序集、模块和类型的对象(Type类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了特性,可以利用反射对它们进行访问。【MSDN】

  1.2 使用场景

    ● 需要访问程序元数据的特性

    ● 检查和实例化程序集中的类型

    ● 在运行时构建新类型。使用System.Reflection.Emit中的类

    ● 执行后期绑定,访问在运行时创建的类型的方法。【MSDN】

  1.3 形象说明

  地球的内部结构:地球的内部结构大体可以分为三层:地壳、地幔和地核。地壳是固体,地核是液体,地幔则是半液半固的结构(地理知识)。如何在地球表面不用深入地球内部就知道其内部结构呢?答案是:向地球发射“地震

波”。地震波分两种,一种是横波,另一种是纵波。横波只能穿透固体,而纵波既可以穿透固体又可以穿透液体。通过在地面对纵波和横波的返回情况,我们就可以大体断定地球内部的构造了。

  B型超声波:大家体检的时候都做过B超吧,B超可以透过肚皮探测到你的内脏的生理情况。这是如何做到的呢?答案是:它可以透过肚皮向你体内发射B型超声波,当超声波遇到内脏壁的时候就会产生一定的“回音”反射,然后

把“回音”进行处理就可以显示出你的内脏的情况了。(部分细节不予追究)

  大家注意到这两个例子的共同特点,就是从一个对象的外部去了解对象内部的构造,而且都是利用了波的反射功能。在.NET中的反射也可以实现从对象的外部来了解对象(或程序集)内部结构的功能,哪怕你不知道这个对象(或

程序集)是什么,另外.NET中的反射还可以动态创建出对象并执行它其中的方法。

  反射是.NET中重要的机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。有了反射,即可对每一个类型了如指掌。另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道。

  1.4 反射的主要用途

  • 使用 Assembly 定义和加载程序集,加载在程序集清单中列出的模块,以及从此程序集中查找类型并创建该类型的实例。

  • 使用 Module 发现以下信息:包含模块的程序集以及模块中的类等。 您还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。

  • 使用 ConstructorInfo 发现以下信息:构造函数的名称、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。 使用 Type 的 GetConstructors 或 GetConstructor 方法来调用特定的构造函数。

  • 使用 MethodInfo 发现以下信息:方法的名称、返回类型、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。 使用 Type 的 GetMethods 或 GetMethod 方法来调用特定的方法。

  • 使用 FieldInfo 发现以下信息:字段的名称、访问修饰符(如 public 或 private)和实现详细信息(如 static)等;并获取或设置字段值。

  • 使用 EventInfo 发现以下信息:事件的名称、事件处理程序数据类型、自定义特性、声明类型和反射类型等;并添加或移除事件处理程序。

  • 使用 PropertyInfo 发现以下信息:属性的名称、数据类型、声明类型、反射类型和只读或可写状态等;并获取或设置属性值。

  • 使用 ParameterInfo 发现以下信息:参数的名称、数据类型、参数是输入参数还是输出参数,以及参数在方法签名中的位置等。

  • 当您在一个应用程序域的仅反射上下文中工作时,请使用 CustomAttributeData 来发现有关自定义特性的信息。 通过使用 CustomAttributeData,您不必创建特性的实例就可以检查它们。【MSDN】

  注:要使用反射,必须使用System.Reflection命名空间

二、Type类

  2.1 简介

  BCL声明了一个叫做Type的抽象类,它被设计用来包含类型的特性,使用这个类的对象能让我们获取程序使用的类型的信息。

   由于Type是抽象类,因此它不能有实例,而是在运行时CLR创建从Type(RuntimeType)派生的类的实例。Type包含了类型信息,当我们要访问这些实例时,CLR不会返回派生类的引用而是返回Type基类的引用。为了简单起见,下面篇幅中我会把引用所指向的对象称为Type类型的对象。

  Type类的重要事项:

    ● 对于程序中用到的每一个类型,CLR都会创建一个包含这个类型信息的Type类型的对象

    ● 程序中用到的每一个类型都会关联到独立的Type类型的对象

    ● 不管创建的类型有多少个实例,只有一个Type对象会关联到所有这些实例

  如果你对C#中有哪些类型不是很了解,那么知识扩展: C#中的类型有:预定义的类型(int,long和string等),BCL中的类型(Console,IEnumerable等)以及用户自定义的类型(MyClass,MyDel等)

  

  2.2 Type类的部分常见成员

成员 成员类型 描述
Name 属性 返回类型的名字
FullName 属性 返回数据类型的完全限定名(包括命名空间名)
NameSpace 属性 返回包含数据类型声明的命名空间
Assembly 属性 返回声明类型的程序集。如果类型是泛型的,返回定义这个类型的程序集
GetConstructor(), GetConstructors() 方法 返回ConstructorInfo类型,用于取得该类的构造函数的信息
GetEvent(), GetEvents() 方法 返回EventInfo类型,用于取得该类的事件的信息
GetField(), GetFields() 方法 返回FieldInfo类型,用于取得该类的字段(成员变量)的信息
GetInterface(), GetInterfaces() 方法 返回InterfaceInfo类型,用于取得该类实现的接口的信息
GetMember(), GetMembers() 方法 返回MemberInfo类型,用于取得该类的所有成员的信息
GetMethod(), GetMethods() 方法 返回MethodInfo类型,用于取得该类的方法的信息
GetProperty(), GetProperties() 方法 返回PropertyInfo类型,用于取得该类的属性的信息

    有关Type类的详细信息请参见【MSDN】

  2.3 获取Type对象

  我们可以使用GetType方法和typeof运算符来获取Type对象。object类型包含了一个叫做GetType的方法,它返回对实例的Type对象的引用。由于每一个类型最终都是从object继承的,所以我们可以在任何类型对象上使用GetType方法来获取它的Type对象

  a.   GetType()用法示例

string str = "fun";
Type t = str.GetType();

  还有一种静态方法:public static Type GetType (string typeName);

Type myType1 = Type.GetType("System.Int32");

  备注:如果typeName找不到,在调用GetType(String)方法将返回null。 它不会引发异常。

  b. typeof用法

Type t1 = typeof(string);

  2.4 示例

using System;
using System.Reflection; namespace Type类使用
{
class Base
{
public int BaseField = ;
} class Derived : Base
{
public int DerivedField = ;
public int change { set; get; }
} class Program
{
static void Main(string[] args)
{
Base b = new Base();
Derived d = new Derived();
Base[] bd = new Base[] { b, d };
foreach(var val in bd)
{
Type t = val.GetType(); //获取类型
Console.WriteLine("object type:{0}", t.Name);
FieldInfo[] fi = t.GetFields(); //获取字段信息
foreach(var f in fi)
{
Console.WriteLine(" Field: {0}", f.Name);
}
}
Console.ReadKey();
}
}
}

上面的例子,是对类中public修饰的成员的操作,实际上private和protected修饰的成员也可以访问到,详情请看:C#之玩转反射

【备注:本文参考了 C#反射详解 ,如有冒犯请联系删除】

C# 反射和Type类的更多相关文章

  1. 反射,System.Type类

    http://m.blog.csdn.net/blog/woddle/40623333 两个现实中的例子:1.B超:大家体检的时候大概都做过B超吧,B超可以透过肚皮探测到你内脏的生理情况.这是如何做到 ...

  2. 反射 介绍System.Type类

    本节先介绍system.Type类,通过这个类可以访问关于任何数据类型的信息. 1. system.Type类以前把Type看作一个类,但它实际上是一个抽象的基类.只要实例化了一个Type对象,实际上 ...

  3. 反射+type类+Assembly+特性

    什么是元数据,什么是反射: 程序是用来处理数据的,文本和特性都是数据,而我们程序本身(类的定义和BLC中的类)这些也是数据. 有关程序及其类型的数据被称为元数据(metadata),它们保存在程序的程 ...

  4. C# - 系统类 - Type类

    Type类 ns:System Type类封装类型 它的实例提供一个特定类型的数据和函数成员的信息 可以使用Type类实例来调用类型的成员 一般将Type类用于反射 Type类的静态字段如下 Empt ...

  5. C# 利用反射动态调用类成员

    用反射动态调用类成员,需要Type类的一个方法:InvokeMember.对该方法的声明如下(摘抄于MSDN): publicobject InvokeMember(    string name, ...

  6. 【java】java反射初探 ——“当类也照起镜子”

    反射的作用   开门见山地说说反射的作用 1.为我们提供了全面的分析类信息的能力 2.动态加载类   我理解的“反射”的意义 (仅个人理解) 我理解的java反射机制就是: 提供一套完善而强大的API ...

  7. 【java】java反射初探 ——“当类也学会照镜子”

    反射的作用   开门见山地说说反射的作用   1.为我们提供了全面的分析类信息的能力 2.动态加载类   我理解的“反射”的意义 (仅个人理解哈)   我理解的java反射机制就是: 提供一套完善而强 ...

  8. Java反射初探 ——“当类也学会照镜子”

    反射的作用 开门见山地说说反射的作用   1.为我们提供了全面的分析类信息的能力 2.动态加载类   我理解的“反射”的意义 (仅个人理解哈)   我理解的java反射机制就是: 提供一套完善而强大的 ...

  9. C# 中利用反射机制拷贝类的字段和属性(拷贝一个类对象的所有东西付给另一个类对象,而不是付给引用地址)

    from:https://blog.csdn.net/poxiaohai2011/article/details/27555951 //C# 中利用反射机制拷贝类的字段和属性(拷贝一个类对象的所有东西 ...

随机推荐

  1. W5100S芯片特性

    W5100S是一款硬连线TCP / IP嵌入式以太网控制器,可使使用SPI(串行外设接口)和并行系统的嵌入式系统更容易实现互联网连接 W5100S适合需要稳定的Internet Connectivit ...

  2. CodeCraft-19 and Codeforces Round #537 (Div. 2) E 虚树 + 树形dp(新坑)

    https://codeforces.com/contest/1111/problem/E 题意 一颗有n个点的树,有q个询问,每次从树挑出k个点,问将这k个点分成m组,需要保证在同一组中不存在一个点 ...

  3. c++两个类相互调用

    有可能会碰到两个类之间的相互调用的问题,例如:定义了类A和类B,A中使用了B定义的类型,B中也使用了A定义的类型 class A { B b; }; class B { A a; }; 编译器在声明A ...

  4. Floyd多源最短路

    可以对每一个顶点使用Dijkstra算法求多源最短路. 这里我们来介绍另一种解法:Floyd Floyd算法的主要思想是迭代.每次迭代会朝着答案更近一步. 首先定义一个二维数组Dk[i][j](k初始 ...

  5. API网关设计(一)之Token多平台身份认证方案(转载)

    原文:https://segmentfault.com/a/1190000018535570?utm_source=tag-newest 概述 今天咱们面对移动互联网的发展,系统一般是多个客户端对应一 ...

  6. [UWP]使用Picker构建应用内图片公共裁剪组件

    在上一篇博文<[UWP]如何实现UWP平台最佳图片裁剪控件>中我讲解了编写ImageCropper控件的过程及知识分享.在那篇文章里,我大言不惭的称其为UWP平台最佳图片裁剪控件(主要是没 ...

  7. 【洛谷4070】 [SDOI2016]生成魔咒(SAM)

    传送门 洛谷 Solution 考虑要求的是什么,前缀的本质不同的字符串个数? 如果只要求一个串那么显然答案是\(\sum_{i=1}^{tot}len[i]-len[fa[i]]\)(实际上这个并不 ...

  8. create-react-app创建的项目npm run build之后静态文件找不到

    create-react-app创建的项目npm run build之后,运行build中的index.html,什么都没显示,打开浏览器的F12,发现了几个红色的报错,提示几个文件找不到. 查看生成 ...

  9. Python脱产8期 Day014 2019/4/28

    一 带参装饰器 1.通常,装饰器为被装饰的函数添加新功能,需要外界的参数 # -- outer参数固定一个,就是func # -- inner参数固定同被装饰的函数,也不能添加新参数 # -- 可以借 ...

  10. java visualVM(jconsole)远程监控服务器java进程

    1. JMX方式(jconsole也可通过此方式进行连接) jmx方式能监控到CPU信息,但无法使用visualVM的visualVM GC插件    jmx无密码方式 监控普通的java进程 . 设 ...