首页 > 学院 > 开发设计 > 正文

.NET 反射详解(转)

2019-11-17 01:59:38
字体:
来源:转载
供稿:网友

.NET 反射详解(转)

概述反射

  • 通过反射可以提供类型信息,从而使得我们开发人员在运行时能够利用这些信息构造和使用对象。
  • 反射机制允许程序在执行过程中动态地添加各种功能。

运行时类型标识

  • 运行时类型标识(RTTI),可以在程序执行期间判定对象类型。例如使用它能够确切地知道基类引用指向了什么类型对象。
  • 运行时类型标识,能预先测试某个强制类型转换操作,能否成功,从而避免无效的强制类型转换异常。
  • 在c#中有三个支持RTTI的关键字:is 、 as 、typeof。 下面依次介绍他们

is运算符:

  通过is运算符,能够判断对象类型是否为特定类型,如果两种类型是相同类型,或者两者之间存在引用,装箱拆箱转换,则表明两种类型是兼容的。

class PRogram    {        static void Main(string[] args)        {            A a = new A();            B b = new B();            if (a is A)              {                Console.WriteLine("a is an A");   //这个打印,因为a 是 A 类型的对象            }            if (b is A)            {                //这个打印,因为b是B类型的对象,而B类型派生于A类型,由于b对象可以转换为A类型,因此b对象与A类型是兼容的,但是反过来就不成立,例如下面不打印                Console.WriteLine("b is an A because it is derived from");             }            if (a is B)            {                //这个不打印                Console.WriteLine("This won't display , because a not derived from B");            }            if (a is object)            {                //这个打印                Console.WriteLine("a is an object");            }            Console.ReadKey();        }    }    class A { }    class B : A { }

as运算符:

  在运行期间执行类型转换,并且能够使得类型转换失败不抛异常,而返回一个null值,其实as也可以看作一个is运算符的简化备选方式(看例子)。

class Program    {        static void Main(string[] args)        {            A a = new A();            B b = new B();            if (a is B)            {                b = (B)a;   //由于a变量不是B类型,因此这里将a变量转换为B类型是无效的。            }            else            {                b = null;            }            if (b ==null)            {                //这个打印                Console.WriteLine("The cast in b=(B)a is not allowed");             }            //上面使用as运算符,能够把两部合二为一。            b = a as B;   //as类型先检查强制类型转换的有效性,如果有效,则执行强类型转换过程。这些都在这一句完成。            if (b == null)            {                //这个打印                Console.WriteLine("The cast in b=(B)a is not allowed");            }            Console.ReadKey();        }    }    class A { }    class B : A { }

typeof运算符:

  as ,is 能够测试两种类型的兼容性。但大多数情况下,还需要获得某个类型的具体信息。这就用到了typeof,它可以返回与具体类型相关的System.Type对象,通过System.Type对象可以去顶此类型的特征。一旦获得给定类型的Type对象,就可以通过使用该对象定义的各种属性,字段,方法来获取类型的具体信息。Type类包含了很多成员,在接下来的反射中再详细讨论。下面简单的演示Type对象,调用它的三个属性。

static void Main(string[] args)        {            Type t=typeof(StringBuilder);            Console.WriteLine(t.FullName);  //FullName属性返回类型的全称            if (t.IsClass)            {                Console.WriteLine("is a class"); //打印            }            if (t.IsSealed)  //是否为密封类            {                Console.WriteLine("is Sealed");  //打印            }            Console.ReadKey();        }

反射的核心类:System.Type类

  • 许多支持反射的类都位于System.Reflection命名空间中,他们是.net Reflection API的一部分,所以在使用的反射的程序中一般都要使用 System.Reflection的命名空间。
  • System. Type类包装了类型,因此是整个反射子系统的核心,这个类中包含了很多属性和方法,使用这些属性和方法可以在运行时得到类型的信息。
  • Type类派生于System.Reflection.MemberInfo抽象类

MemberInfo类中的只读属性

属性

描述

TypeDeclaringType

获取声明该成员的类或接口的类型

MemberTypesMemberType

获取成员的类型,这个值用于指示该成员是字段、方法、属性、事件、或构造函数

IntMetadataToken

获取与特定元数据相关的值

ModuleModule

获取一个代表反射类型所在模块(可执行文件)的Module对象

StringName

成员的名称

TypeReflectedType

反射的对象类型

请注意

  • MemberType属性的返回类型为MemberTypes,这是一个枚举,它定义了用于表示不同成员的类型值。这些值包括:MemberTypes.Constructor, MemberTypes.Method, MemberTypes.Field, MemberTypes.Event, MemberTypes.Property。因此可以通过检查MemberType属性来确定成员的类型,例如,在MemberType属性的值为MemberTypes.Method时,该成员为方法
  • MemberInfo类还包含两个与特性相关的抽象方法:
    1. GetCustomAttributes() :获得与主调对象关联的自定义特性列表。
    2. IsDefined(): 确定是否为主调对象定义了相应的特性。
    3. GetCustomAttributesData():返回有关自定义特性的信息(特性稍后便会提到)

当然除了MemberInfo类定义的方法和属性外,Type类自己也添加了许多属性和方法:如下表(只列出一些常用的,太多了,自己可以转定义Type类看下)

Type类定义的方法

方法

功能

ConstructorInfo[] GetConstructors()

获取指定类型的构造函数列表

EventInfo[] GetEvents();

获取指定类型的时间列

FieldInfo[] GetFields();

获取指定类型的字段列

Type[] GetGenericArguments();

获取与已构造的泛型类型绑定的类型参数列表,如果指定类型的泛型类型定义,则获得类型形参。对于正早构造的类型,该列表就可能同时包含类型实参和类型形参

MemberInfo[] GetMembers();

获取指定类型的成员列表

MethodInfo[] GetMethods();

获取指定类型的方法列表

PropertyInfo[] GetProperties();

获取指定类型的属性列表

下面列出Type类定义的常用的只读属性

Type类定义的属性

属性

功能

Assembly Assembly

获取指定类型的程序集

TypeAttributes Attributes

获取制定类型的特性

Type BaseType

获取指定类型的直接基类型

String FullName

获取指定类型的全名

bool IsAbstract

如果指定类型是抽象类型,返回true

bool IsClass

如果指定类型是类,返回true

string Namespace

获取指定类型的命名空间

使用反射

上面的列术都是为了,这里的使用。

通过使用Type类定义的方法和属性,我们能够在运行时获得类型的各种具体信息。这是一个非常强大的功能。我们一旦得到类型信息,就可以调用其构造函数,方法,和属性。可见,反射是允许使用编译时不可用的代码的。

由于Reflection API非常多,这里不可能完整的介绍他们(这里如果完整的介绍,据说要一本书,厚书)。但是,Reflection API是按照一定逻辑设计的。因此,只要知道部分接口的使用方法,就可以举一反三的使用剩余的接口。

这里我列出四种关键的反射技术:

  1. 获取方法的信息
  2. 调用方法
  3. 构造对象
  4. 从程序集中加载类型

获取方法的相关信息

一旦有了Type对象就可以使用GetMethodInfo()方法获取此类型支持的方法列表。该方法返回一个MethodInfo 对象数组,MethodInfo对象描述了主调类型所支持的方法,他位于System.Reflection命名空间中

MethodInfo类派生于Method

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表