zoukankan      html  css  js  c++  java
  • [c#进阶系列一]:理解反射(Reflection)

    "反射"是.NET中的重要技术,通过反射,可以在运行时获得某个类型的各种信息,进而动态的创建对象实例,完成方法调用,属性设置和事件激发。在.NET中“代码特性(Attribute)”就利用了反射技术。

    反射技术的基础

    反射的特点:允许一个对象的类型带程序运行时才确定。

    反射作用:这个技术在实际开发中很有用,它使我们可以动态的替换掉系统中的某一部分而不用重新编译源码。

    反射概述

    反射的基本作用:运行期,根据对象名就能获得该对象的:类型方法属性,还可以获得每个成员的名称,访问权限和参数信息,这些信息都存储于元数据中,因此反射处理的对象是程序集元数据。

    注:著名的Reflector软件就是利用反射技术编写的,可以查看.NET程序集中的所有数据类型,并反编译为C#等语言的源代码。

    .NET程序集的层次结构

    C#程序中声明的“类型”包含成员,比如类中就包含方法,属性,字段等成员,并且按照命名空间进行组织,类就是类型(Type)的示例。在编译程序的时候被打包为程序集(通常拓展名为exe或dll,前者可直接执行,后者必须加载到进程中才能被执行)。

    在System.Reflection命名空间内包含多个反射常用的类,下面表格列出了常用的几个类。

    类型         作用
    Assembly      通过此类可以加载操纵一个程序集,并获取程序集内部信息
    EventInfo      该类保存给定的事件信息
    FieldInfo        该类保存给定的字段信息
    MethodInfo      该类保存给定的方法信息
    MemberInfo     该类是一个基类,它定义了EventInfo、FieldInfo、MethodInfo、PropertyInfo的多个公用行为
    Module        该类可以使你能访问多个程序集中的给定模块
    ParameterInfo     该类保存给定的参数信息      
    PropertyInfo      该类保存给定的属性信息

    上述的信息被存放在模块的源数据中,使用System.Type类代表抽象的数据类型,我们可以使用顶层的Object类提供的GetType()方法来获得它所对应的Type对象。

    数据类型的奥秘System.Type类

    Type类是一个特殊的数据类型,他是可以表达数据类型信息的数据类型。参照下面的代码理解

    public class cla1
    {
         public int i;
         public void met(){}
         public string pro{get;set;}
    }

    上诉代码定义了一个public类型的cla1,拥有以下类型

    1)类名cla1,公有,

    2)父类为Object类

    3)公有字段 i

    4)公有方法 met()

    5)公有属性 pro

    上述的信息都被封装到了Type类型的对象中。Type是最常用到的类,通过Type可以得到一个类的内部信息,也可以通过它反射创建一个对象。一般有三个常用的方法可以得到Type对象。

    1.利用typeof()得到Type对象

    cla1 c1= new cla1(); 
    Type type = typeof(cla1);

    2.利用System.Object.GetType()得到Type对象

      cla1 c1= new cla1();
      Type type = c1.GetType();

    3.利用System.Type.GetType()得到Type对象

    Type type = Type.GetType("MyAssembly.cla1",false,true)   //注意0是类名,参数1表示若找不到对应类时是否抛出异常,参数2表示类名是否区分大小写

    三者的区别在于:

    typeof()和Type.GetType()是从一个类中获取对象,而Object.GetType()是从一个类的实例获得对象。

    而前两者的区别在于

    • Typeof()是运算符而GetType是方法
    • GetType()是基类System.Object的方法,因此只有建立一个实例之后才能够被调用(初始化以后)
    • Typeof()的参数只能是int,string,String,自定义类型,且不能是实例
    • GetType() 和typeof()都返回System.Type的引用。

    动态对象的创建与方法的调用

    读者读到这里 的时候一定会问,我知道这些信息能做什么,其实 一旦你拿到这些Type对象的信息就可以在需要的时候创建这一类型的对象,并且调用它的方法,并且保存此类型的Assembly文件,并不需要添加程序集引用。

    动态对象创建

    Assembly类有一个CreateInstance方法,用于创建对象,其定义为

    public Object CreateInstance(string typename);

    只要传给这个方法一个类型名称的字符串就可以创建一个对象。

    复制代码
        class Program
        {
            static void Main(string[] args)
            {
                Assembly assm = Assembly.Load("fanshe");
                Console.WriteLine(assm.FullName);   //输出 fanshe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
    
                //注释上面两行,移除程序集的引用
    
                Assembly assm1 = Assembly.LoadFrom(@"D:\fanshe.dll");
                Console.WriteLine(assm1.FullName);      ////输出 fanshe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
    
                //与Assembly.LoadFrom基本一样,只是如果被加载的dll,还依赖其他的dll的话,它不会加载
                Assembly assm2 = Assembly.LoadFile(@"D:\fanshe.dll");
                Console.WriteLine(assm2.FullName);
    
                Console.ReadKey();
            }
        }
    复制代码
  • 相关阅读:
    BZOJ 1046: [HAOI2007]上升序列(LIS)
    BZOJ 1001: [BeiJing2006]狼抓兔子(最短路)
    UVa 12299 RMQ with Shifts(线段树)
    NOIP2010提高组] CODEVS 1069 关押罪犯(并查集)
    [NOIP2001提高组]CODEVS1014 Car的旅行路线(最短路)
    scp 远程文件拷贝命令
    mysql yum源安装极速
    ssh pubkey免密登陆远程主机
    paramiko linux pip18.1
    python3 linux
  • 原文地址:https://www.cnblogs.com/yeanzhi/p/3067865.html
Copyright © 2011-2022 走看看