• 反射学习笔记二(转载)


    反射概述 和Type类

    1.反射的作用

    简单来说,反射提供这样几个能力:1、查看和遍历类型(及其成员)的基本信息和程序集元数据(metadata);2、迟绑定(Late-Binding)方法和属性。3、动态创建类型实例(并可以动态调用所创建的实例的方法、字段、属性)。序章中,我们所采用的那个例子,只是反射的一个用途:查看类型成员信息。接下来的几个章节,我们将依次介绍反射所提供的其他能力。

    2.获取Type对象实例

    反射的核心是Type类,这个类封装了关于对象的信息,也是进行反射的入口。当你获得了关于类型的Type对象后,就可以根据Type提供的属性和方法获取这个类型的一切信息(方法、字段、属性、事件、参数、构造函数等)。我们开始的第一步,就是获取关于类型的Type实例。获取Type对象有两种形式,一种是获取当前加载程序集中的类型(Runtime),一种是获取没有加载的程序集的类型。

    我们先考虑Runtime时的Type,一般来说有三种获取方法:

    2.1使用Type类提供的静态方法GetType()

    比如我们想要获得Stream类型的Type实例,则可以这样:

    Type t = Type.GetType("System.IO.Stream");
    txtOutput.Text = t.ToString();

    注意到GetType方法接受字符串形式的类型名称。

    2.2 使用 typeof 操作符

    也可以使用C# 提供的typeof 操作符来完成这一过程:

    // 如果在页首写入了using System.IO; 也可以直接用 typeof(Stream);
    Type t = typeof(System.IO.Stream);

    这时的使用有点像泛型,Stream就好像一个类型参数一样,传递到typeof操作符中。

    2.3 通过类型实例获得Type对象

    我们还可以通过类型的实例来获得:

    String name = "Jimmy Zhang";
    Type t = name.GetType();

    使用这种方法时应当注意,尽管我们是通过变量(实例)去获取Type对象,但是Type对象不包含关于这个特定对象的信息,仍是保存对象的类型(String)的信息。

    3.Type类型 及 Reflection命名空间的组织结构

    到现在为止,我已经多次提过Type封装了类型的信息,那么这些类型信息都包含什么内容呢?假设我们现在有一个类型的实例,它的名字叫做 demo,我们对它的信息一无所知,并通过下面代码获取了对于它的Type实例:

    // 前面某处的代码实例化了demo对象
    Type t = demo.GetType();

    现在,我们期望 t 包含了关于 demo 的哪些信息呢?

    3.1 demo的类型的基本信息

    • 我们当然首先想知道 demo 是什么类型的,也就是 demo 的类型名称。
    • 我们还想知道该类型位于什么命名空间下。
    • 它的基类型是什么,以及它在.Net运行库中的映射类型。
    • 它是值类型还是引用类型。
    • 它是不是Public的。
    • 它是枚举、是类、是数组、还是接口。
    • 它是不是基础类型(int等)。
    • 等等 ...

    Type 提供了下面的属性,用于获取类型的基本信息,常用的有下面一些:

    属 性 说 明
    Name 获取类型名称
    FullName 类型全名
    Namespace 命名空间名称
    BaseType 获取对于基类的Type类型的引用
    UnderlyingSystemType 在.Net中映射的类型的引用
    Attributes 获取TypeAttributes位标记
    IsValueType 是否值类型
    IsByRef 是否由引用传递
    IsEnum 是否枚举
    IsClass 是否类
    IsInterface 是否接口
    IsSealed 是否密封类
    IsPrimitive 是否基类型(比如int)
    IsAbstract 是否抽象
    IsPublic 是否公开
    IsNotPublic 是否非公开
    IsVisible 是否程序集可见
    等等...  

    3.2 demon的类型的成员信息  

    • 我们可能还想知道它有哪些字段。
    • 有些什么属性,以及关于这些属性的信息。
    • 有哪些构造函数。
    • 有哪些方法,方法有哪些参数,有什么样的返回值。
    • 包含哪些事件。
    • 实现了哪些接口。
    • 我们还可以不加区分地获得它的所有 以上成员。

    观察上面的列表,就拿第一条来说,我们想获取类型都有哪些字段,以及这些字段的信息。而字段都包含哪些信息呢?可能有字段的类型、字段的名称、字段是否public、字段是否为const、字段是否是read only 等等,那么是不是应该将字段的这些信息也封装起来呢?

    实际上,.Net中提供了 FiledInfo 类型,它封装了关于字段的相关信息。对照上面的列表,类似的还有 PropertyInfo类型、ConstructorInfo类型、MethodInfo类型、EventInfo类型。而对于方法而言,对于它的参数,也会有in参数,out参数,参数类型等信息,类似的,在 System.Reflection 命名空间下,除了有上面的提到的那么多Info后缀结尾的类型,还有个ParameterInfo 类型,用于封装方法的参数信息。

    最后,应该注意到 Type 类型,以及所有的Info类型均 继承自 MemberInfo 类型,MemberInfo类型提供了获取类型基础信息的能力。

    在VS2005中键入Type,选中它,再按下F12跳转到Type类型的定义,纵览Type类型的成员,发现可以大致将属性和方法分成这样几组:

    • IsXXXX,比如 IsAbstract,这组bool属性用于说明类型的某个信息。(前面的表格已经列举了一些。)
    • GetXXXX(),比如GetField(),返回FieldInfo,这组方法用于获取某个成员的信息。
    • GetXXXXs(),比如GetFields(),返回FieldInfo[],这组方法用户获取某些成员信息。
    • 还有其他的一些属性和方法,等后面遇到了再说。

    由于MemberInfo是一个基类,当我们获得一个MemberInfo后,我们并不知道它是PropertyInfo(封装了属性信息的对象)还是FieldInfo(封装了属性信息的对象),所以,有必要提供一个办法可以让我们加以判断,在Reflection 命名空间中,会遇到很多的位标记,这里先介绍第一个位标记(本文管用[Flags]特性标记的枚举称为 位标记),MemberTypes,它用于标记成员类型,可能的取值如下:

    [Flags]
    public enum MemberTypes {
        Constructor = 1,  //  该成员是一个构造函数
        Event = 2,        //  该成员是一个事件
        Field = 4,        //  该成员是一个字段
        Method = 8,           //  该成员是一个方法
        Property = 16,    //  该成员是一个属性
        TypeInfo = 32,    //  该成员是一种类型
        Custom = 64,      //  自定义成员类型
        NestedType = 128, //  该成员是一个嵌套类型
        All = 191,        //  指定所有成员类型。
    }

     

    转自:http://www.cnblogs.com/JimmyZhang/archive/2008/02/17/1071372.html

  • 相关阅读:
    第二天课程档案
    第一天课程档案
    SAM初步
    计算几何初步
    数论二次总结
    生成函数入门题汇总
    1500: [NOI2005]维修数列
    20170214
    【bzoj2286】[Sdoi2011]消耗战
    bzoj2223: [Coci 2009]PATULJCI
  • 原文地址:https://www.cnblogs.com/johnwonder/p/1672266.html
Copyright © 2020-2023  润新知