C#基础篇——反射

前言

在探究地球内部的结构中,如何做到在地球表面不用深入地球内部就可以知道内部的构造呢?其实,向地球发射“地震波”。利用这种方式,可以判断地球放回的情况,大体上,我们也可以断定地球内部的构造了。

从这个例子中,通过一个对象的外部去了解对象内部的构造,都是利用了波的反射功能。而利用这种原理,在编程程序时,我们如何也可以实现从对象的外部来了解对象以及程序集内部的结构功能?在.NET中的反射,不仅可以实现外部对内部的了解,也同时可以动态创建出对象并执行其中的方法。.

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

开始

 一、使用的命名空间

   System.Reflection
    System.Type
    System.Reflection.Assembly

二、主要的类

   System.Type 类--通过这个类可以访问任何给定数据类型的信息。
    System.Reflection.Assembly类--它可以用于访问给定程序集的信息,或者把这个程序集加载到程序中。

说明

 一、System.Type类

 System.Type类对反射起着核心的作用。它是一个抽象的基类,Type有与每种数据类型对应的派生类,我们使用这个派生类的对象的方法、字段、属性来查找有关该类型的所有信息。

表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。

从Type中解析类型信息:

C#基础篇——反射

 A、判断给定类型的引用的常用方式:

1. 使用C# typeof运算符

 Type t = typeof(string);

2.使用对象GetType()方法

  string s = "i3yuan";
  Type t2 = s.GetType();

3.调用静态Type类的静态方法GetType()

  Type t3 = Type.GetType("System.String");

以上三种方式获取类型Type后,可以应用t来探测string里面的结构

  foreach (MemberInfo mi in t.GetMembers())
  {
       Console.WriteLine("{0}/t{1}", mi.MemberType, mi.Name);
  }

B、Type类属性:

 1.命名空间和类型名

       Name 数据类型名
        FullName 数据类型的完全限定名(包括命名空间名)
        Namespace 定义数据类型的命名空间名

 2. 类和委托

       Type.IsClass   判断一个类型是否为类或者委托。符合条件的会有普通的类(包括泛型)、抽象类(abstractclass)、委托(delegate)

 3. 是否泛型  

       Type.IsGenericType 属性可以判断类或委托是否为泛型类型。

       Type.IsGenericTypeDefinition 属性可以判断Type是否是未绑定参数类型的泛型类型。

       Type.IsConstructedGenericType 属性判断是否可以此Type创建泛型实例。

 4.访问修饰符

       Type.IsPublic 判断该类型是否是公有的

       Type.IsNotPublic

 5.密封类、静态类型、抽象类

       Type.IsSealed 判断该类型是否是密封类,密封类不能被继承

       IsAbstract 指示该类型是否是抽象类型

 6. 值类型

       Type.IsValueType 判断一个 Type 是否为值类型,简单值类型、结构体、枚举,都符合要求。

       Type.IsEnum   判断该类型是否是枚举

       Type.IsPrimitive  判断Type是否为基础类型

 7.接口

       Type.IsInterface    判断该类型是否是接口

 8.数组

       IsArray   判断该类型是否是数组,GetArrayRank() 获取数组的维数。

从Type类解析类型成员结构

C#基础篇——反射

一个类由以下一个或多个成员组成:

成员类型

说明

PropertyInfo

类型的属性信息

FieldInfo

类型的字段信息

ConstructorInfo

类型的构造函数信息

MethodInfo

类型的方法

ParameterInfo

构造函数或方法的参数

EventInfo

类型的事件

C、Type类的方法

C#基础篇——反射   

       GetConstructor(), GetConstructors():返回ConstructorInfo类型,用于取得该类的构造函数的信息

C#基础篇——反射

       GetEvent(), GetEvents():返回EventInfo类型,用于取得该类的事件的信息

       GetField(), GetFields():返回FieldInfo类型,用于取得该类的字段(成员变量)的信息

C#基础篇——反射

       GetInterface(), GetInterfaces():返回InterfaceInfo类型,用于取得该类实现的接口的信息

       GetMember(), GetMembers():返回MemberInfo类型,用于取得该类的所有成员的信息

C#基础篇——反射

       GetMethod(), GetMethods():返回MethodInfo类型,用于取得该类的方法的信息

C#基础篇——反射

       GetProperty(), GetProperties():返回PropertyInfo类型,用于取得该类的属性的信息

C#基础篇——反射

 可以调用这些成员,其方式是调用Type的InvokeMember()方法,或者调用MethodInfo,PropertyInfo和其他类的Invoke()方法。 

  用反射生成对象,并调用属性、方法和字段进行操作 

C#基础篇——反射

二、System.Reflection.Assembly类

  Assembly类可以获得程序集的信息,也可以动态的加载程序集,以及在程序集中查找类型信息,并创建该类型的实例。使用Assembly类可以降低程序集之间的耦合,有利于软件结构的合理化

 1.System.Reflection 

用于访问给定程序集的信息,或者把这个程序集加载到程序中。可以读取并使用metadata

方法调用过程:

1.加载DLL  ; 2. 获取类型信息;3. 创建对象类型  4. 类型转换  5. 方法调用

C#基础篇——反射

方法二:通过程序集的名称反射

C#基础篇——反射

总结

 1. 作为一个开发人员,在每天都会应用到反射,使用的时候,会反射当前程序的元数据,将所有的方法,类等信息都全部显示出来,以便开发人员使用,大大的提高了效率

 2. 同时反射提高了程序的灵活性和拓展性,降低耦合,动态加载,允许控制和实现任何类的对象。

 3. 当然了,也存在弊端,写起来复杂,也存在性能问题,用于字段和方法接入时要远慢于直接代码。