一、元数据和反射

  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. python 去除字符串末尾的子串

    建议使用 "字符串".replace("要去除的字符串", "") 尽量不要使用 strip() ,有时会引入意想不到的结果.strip() ...

  2. Android Studio 内置SDK在 unity中使用

    1 AndroidStudio 安装好后更新SDK Platforms 2 在 File -> Other Settings -> Default Project Structure 中可 ...

  3. memmove、memcpy和memccpy简介

    memmove.memcpy和memccpy三个函数都是内存的拷贝,从一个缓冲区拷贝到另一个缓冲区.memmove(void *dest,void*src,int count)memcpy(void ...

  4. Codeforces Round #547 (Div. 3) G 贪心

    https://codeforces.com/contest/1141/problem/G 题意 在一棵有n个点的树上给边染色,连在同一个点上的边颜色不能相同,除非舍弃掉这个点,问最少需要多少种颜色来 ...

  5. IntelliJ IDEA使用心得之Maven项目篇(转)

    IntelliJ IDEA使用心得之Maven项目篇   今天和大家分享下,在IDEA中打开Maven项目的方法. 对于新版的IDEA可以直接打开Maven项目,但是对于旧版的IDEA需要使用Mave ...

  6. MySQL之二 yum安装及初识

      安装   yum install mysql-server chkconfig -list mysqld 查看mysqld服务是否为开机启动 chkconfig mysqld on 设为开机启动 ...

  7. Codeforces Round #541--1131F. Asya And Kittens(基础并查集)

    https://codeforces.com/contest/1131/problem/F #include<bits/stdc++.h> using namespace std; int ...

  8. ·通过wifi_scan学习esp32wifi程序编写

    在ESP32的设计开发中,我们必然会需要使用到wifi或ble功能,今天就讲解下如何将WIFI功能纳入到ESP32中来. 初始化WiFi环境 首先,WiFi子系统的初始化需要由我们自己来自行,当我们写 ...

  9. html 基本用法

    html表单表格基本用法,直接贴代码. <html> <head> <title>html基础</title> </head> </b ...

  10. Javascript高级编程学习笔记(6)—— 流程控制语句

    话不多说,我们直接开始进入今天的主题 流程控制语句 首先什么是流程控制语句呢? 顾名思义,就是控制流程的语句. 在JS中语句定义了ECMAScript中的主要语法,让我们可以使用一系列的关键字来完成指 ...