一、元数据和反射

  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. [SoapUI] 检查测试步骤的类型或者或者某种特定类型的步骤列表

    SoapUI Groovy : Check if test step is of specific type, such as : Wsdl, Rest, Jdbc, HTTP, Groovy etc ...

  2. 亲写javascript 各类面试题

    DOM修改: 1.全文单词首字母大写---2013 腾讯 var toCapitalize = function (str){ var aStr1 = str.split(" ") ...

  3. vi分屏指令

    用vi打开,view打开vsplit不支持 命令模式下::new,新建文件并分屏, 快捷键,Ctrl+W,然后马上按n键:spilt 水平分屏,将当前屏分为两个,水平的.   Ctrl + w, s: ...

  4. 可遇不可求的Question之skip-name-resolve模式篇

    mysql启用skip-name-resolve模式时出现Warning的处理办法 在优化MYSQL配置时,加入 skip-name-resolve ,在重新启动MYSQL时检查启动日志,发现有警告信 ...

  5. TabLoaout简单框架

    import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design. ...

  6. org.apache.subversion.javahl.ClientException: Previous operation has not finished

    1.问题 eclipse使用SVN出现异常: org.apache.subversion.javahl.ClientException: Previous operation has not fini ...

  7. 《mysql必知必会》学习_第18章_20180807_欢

    第18章 全文本搜索 P121  #创建一个新表,对表的列进行定义,定义之后,MySQL自动维护该索引# create table productnotes ( note_id  int   NOT ...

  8. WPF数字滚动效果

    和WPF数字滚动抽奖有区别,WPF数字滚动抽奖是随机的,而这里是确定的. 为了系统演示,这个效果通宵加班写了整整6个小时,中间就上了次厕所. 代码: RollingNumberItemCtrl.xam ...

  9. video设置autoplay 不起作用

    video 标签上添加 muted https://blog.csdn.net/taiyangmiaomiao/article/details/80266625

  10. ssh命令-使用密钥文件进行登陆

    在win上面可以使用XSHELL来登录类似于阿里云这样的安全服务器,在ubuntu上面就可以使用系统自带的命令工具来连接 使用命令 ssh -i key.pem [server] 实例如下: ssh ...