zoukankan      html  css  js  c++  java
  • 14反射程序集

    1、什么是程序集?
    程序集是.net中的概念。
    .net中的dll与exe文件都是程序集。程序集(Assembly),可以看作是一堆相关类打一个包,相当于Java中的jar包(*)
     
    程序集包含:类型元数据(描述在代码中定义的每一类型和成员,二进制形式)、程序元数据(程序集清单、版本号、名称等)、IL代码(这些都被装在exe或dll中)、资源文件。每个程序集都有自己的名称、版本等信息。这些信息可以通过AssemblyInfo.cs文件来定义。
     
    使用程序集的好处:
    程序中只引用必须的程序集,减小程序的尺寸。
    程序集可以封装一些代码,只提供必要的访问接口。
     
    如何添加程序集的引用?
    添加路径、项目引用、GAC(全局程序集缓存)
    不能循环添加引用
    在C#中添加其它语言编写的dll文件的引用》(参考P/Invoke,在.net中调用非程序集的dll) extern
     
     
    2、反射

    反射无处不在,我们天天在使用。VS的智能提示,就是通过反射获取到类的属性、方法等。还有反编译工具也是通过反射实现。

    反射就是动态获取程序集的元数据(提供程序集的类型信息)的功能。

    反射就是动态获取程序集中的元数据来操作类型的

    Type类实现反射的一个重要的类,通过它我们可以获取类中的所有信息,包括方法、属性等。可以动态调用累的属性、方法。Type是对类的描述。

    反射就是直接通过 .dll 来创建对象,调用成员。

    通过类型元数据来获取对象的一些相关信息,并且还可以实例化对象调用方法等,这个就叫做 ”反射” 。

    反射让创建对象的方式发生了改变。

    编译器的智能提示就是反射的一个应用。

    3、Type类

    Type类的使用

    通过类获得Type:    Type t = typeof( person )

    通过对象获得类的Type:    Type t = p.GetType( )

    动态加载程序集

    string path = @"F:MyCSharp练习练习ClassLibrary1inDebugClassLibrary1.dll";
    //加载程序集
    Assembly asm = Assembly.LoadFile(path);

     

    调用 Assembly 的 GetExportedTypers 方法可以得到 Assembly 中定义的所有 public 类型

    Type[] types = asm.GetExportedTypes();//获得程序集中定义的所有 public 类型  返回值是一个类型数组

     

    调用 Assembly 的 GetTpye( name ) 方法可以得到 Assembly 中定义的全名为 name 的类型信息

    //获取指定的某个类型,必须写该类型的"全名"(完全限定名称:ClassLibrary1.Person)
    Type typePerson = asm.GetType("ClassLibrary1.Person");
    4、动态创建对象

    GetConstructor ( 参数列表 ) ;  //这是一个找到带参数的构造函数

    Activator.CreateInstance( Type t )  会动态调用类的无参构造函数创建一个对象,返回值就是创建的对象,如果类没有无参构造函数机会报错

    string path = @"F:MyCSharp练习练习ClassLibrary1inDebugClassLibrary1.dll";
    //加载程序集
    Assembly asm = Assembly.LoadFile(path);
    //获得某个类型的Type
    Type typeStudent = asm.GetType("ClassLibrary1.Student");
    Type typePerson = asm.GetType("ClassLibrary1.Person");
    Type typeIFlyable = asm.GetType("ClassLibrary1.IFlyable");
    //使用CreateInstance(Type t) 创建对象
    object student = Activator.CreateInstance(typeStudent);//调用的是无参的构造函数
    object person = Activator.CreateInstance(typePerson);//调用的是无参的构造函数
     

    Type类的方法:在编写调用插件的程序时,需要做一系列验证。

    bool IsAssignableFrom( Type c );     判断当前的类型的变量是不是可以接受 c 类型变量的赋值。

     1 //1、IsAssignableFrom(),就是验证是否可以将某个类型的对象赋值给另外一个类型的变量
     2 string path = @"F:MyCSharp练习练习ClassLibrary1inDebugClassLibrary1.dll";
     3 //加载程序集
     4 Assembly asm = Assembly.LoadFile(path);
     5 //获得某个类型的Type
     6 Type typeStudent = asm.GetType("ClassLibrary1.Student");
     7 Type typePerson = asm.GetType("ClassLibrary1.Person");
     8 Type typeIFlyable = asm.GetType("ClassLibrary1.IFlyable");
     9 //返回true 表示可以将 typeStudnet 的对象赋值给 typePerson 类型
    10 Console.WriteLine(typePerson.IsAssignableFrom(typeStudent));
    11 //是否可以把 typeStudent 对象赋值给 typeIFlyable 类型变量
    12 Console.WriteLine(typeIFlyable.IsAssignableFrom(typePerson));
    13 //是否可以把 typeStudent 对象赋值给 typeIFlyable 类型变量
    14 Console.WriteLine(typeIFlyable.IsAssignableFrom(typeStudent));
    15 Console.ReadKey();
     

     

        bool IsInstanceOfType( object o );    判断对象o是否是当前类的实例(当前类可以是o的类、父类、接口)

     1 string path = @"F:MyCSharp练习练习ClassLibrary1inDebugClassLibrary1.dll";
     2 //加载程序集
     3 Assembly asm = Assembly.LoadFile(path);
     4 //获得某个类型的Type
     5 Type typeStudent = asm.GetType("ClassLibrary1.Student");
     6 Type typePerson = asm.GetType("ClassLibrary1.Person");
     7 Type typeIFlyable = asm.GetType("ClassLibrary1.IFlyable");
     8 object student = Activator.CreateInstance(typeStudent);
     9 object person = Activator.CreateInstance(typePerson);
    10 //person 这个对象是否是当前指定的 typePerson 的对象
    11 Console.WriteLine(typePerson.IsInstanceOfType(person));//true
    12 //student 这个对象是否是当前指定的 typePerson 的对象
    13 Console.WriteLine(typePerson.IsInstanceOfType(student));//true
    14 //person 这个对象是否是当前指定的 typeStudent 的对象
    15 Console.WriteLine(typeStudent.IsInstanceOfType(person));//false
    16 //student 这个对象是否是当前指定的 typeStudent 的对象
    17 Console.WriteLine(typeStudent.IsInstanceOfType(student));//true
    18 //person 这个对象是否是当前指定的 typeIFlyable 的对象
    19 Console.WriteLine(typeIFlyable.IsInstanceOfType(person));//false
    20 //student 这个对象是否是当前指定的 typeIFlyable 的对象
    21 Console.WriteLine(typeIFlyable.IsInstanceOfType(student));//true
    22 Console.ReadKey();
     

        bool IsSubclassOf( Type c );    判断当前类是否是类c的子类。(与接口无关)

     1 //3、IsSubclassOf(Type c)    判断当前类是否是类 c 的子类,只是类,没有接口的事
     2 string path = @"F:MyCSharp练习练习ClassLibrary1inDebugClassLibrary1.dll";
     3 //加载程序集
     4 Assembly asm = Assembly.LoadFile(path);
     5 //获得某个类型的Type
     6 Type typeStudent = asm.GetType("ClassLibrary1.Student");
     7 Type typePerson = asm.GetType("ClassLibrary1.Person");
     8 Type typeIFlyable = asm.GetType("ClassLibrary1.IFlyable");
     9 //创建指定类型的对象
    10 object student = Activator.CreateInstance(typeStudent);
    11 object person = Activator.CreateInstance(typePerson);
    12 //判断 typeStudent 是否是 typePerson 的子类
    13 Console.WriteLine(typeStudent.IsSubclassOf(typePerson));//true
    14 //判断 typePerson 是否是 typeIFlyable 的子类
    15 Console.WriteLine(typePerson.IsSubclassOf(typeIFlyable));//false
    16 //判断 typeStudent 是否是 typeIFlyable 的子类
    17 Console.WriteLine(typeStudent.IsSubclassOf(typeIFlyable));//false
    18 Console.ReadKey();

     

        IsAbstract    判断是否为抽象的,包含接口

     1 //4、IsAbstract  判断是否为抽象的,含接口
     2 string path = @"F:MyCSharp练习练习ClassLibrary1inDebugClassLibrary1.dll";
     3 
     4 //加载程序集
     5 Assembly asm = Assembly.LoadFile(path);
     6 
     7 //获得某个类型的Type
     8 Type typeStudent = asm.GetType("ClassLibrary1.Student");
     9 Type typePerson = asm.GetType("ClassLibrary1.Person");
    10 Type typeIFlyable = asm.GetType("ClassLibrary1.IFlyable");
    11 Type typeMyclass1 = asm.GetType("ClassLibrary1.MyClass1");
    12 Type typeMyclass2 = asm.GetType("ClassLibrary1.MyClass2");
    13 
    14 //创建指定类型的对象
    15 object student = Activator.CreateInstance(typeStudent);
    16 object person = Activator.CreateInstance(typePerson);
    17 
    18 //判断是否为抽象的,含接口
    19 Console.WriteLine(typeStudent.IsAbstract);//false
    20 Console.WriteLine(typePerson.IsAbstract);//false
    21 Console.WriteLine(typeIFlyable.IsAbstract);//true
    22 Console.WriteLine(typeMyclass1.IsAbstract);//true
    23 Console.WriteLine(typeMyclass2.IsAbstract);//true
    24 
    25 Console.ReadKey();
    5、动态调用成员

    MemberInfo类    抽象类,有很多子类,下面所有类都继承自 MemberInfo 类:

    PropertyInfo    获取属性

    1 //所有的属性
    2 PropertyInfo[] properties = typePerson.GetProperties();
    3 //通过循环输出每一个属性的名称
    4 for (int i = 0; i < properties.Length; i++)
    5 {
    6     //循环输出
    7     Console.WriteLine(properties[i].Name);
    8 }
    9 Console.ReadKey(); 
     

    主要成员:

    CanRead、CanWrite、PropertyType属性类型;

    SetValue、GetValue:读取值、设置值第一个参数是实例对象,因为set、get要针对具体实例,最后一个参数 null 。pInfo.SetValue( p1, 30, null );

     

    MethodInfo    获取方法

    1 //获取 Person 类中的所有的方法
    2 MethodInfo[] methods = typePerson.GetMethods();
    3 //遍历获取到的所有方法的数组
    4 for (int i = 0; i < methods.Length; i++)
    5 {
    6     //输出所有方法的方法名
    7     Console.WriteLine(methods[i].Name);
    8 }
    9 Console.ReadKey(); 
    获得某一个指定的方法
    1. 1 //获得Person类名字为SayHi的方法,并且是没有任何参数的方法
      2 MethodInfo method = typePerson.GetMethod("SayHi")

    调用这个方法

    1.  1 MethodInfo method = typePerson.GetMethod("SayHi");
       2 //判断获得的方法是否为空
       3 if (method != null)
       4 {
       5     //因为SayHi()方法是一个实例方法,不是静态方法,所以调用SayHi()方法的时候,必须在某个对象上调用,所以method.Invoke() 需要传递一个具体的Person对象进去
       6     object obj = Activator.CreateInstance(typePerson);//创建一个Person对象
       7         //调用Invoke() 方法要把person创建的对象传进来
       8     method.Invoke(obj, null);//调用SayHi()方法,如果这个方法没有参数第二个参数为null
       9 }
      10 else
      11 {
      12     Console.WriteLine("找不懂啊你要调用的方法");
      13 }
      14 Console.ReadKey(); 
     
    调用这个方法的重载方法
    1. //获得方法名为 SayHi 的重载方法(第二个参数为对应类型的参数:typeof(参数相应类型))
      MethodInfo method = typePerson.GetMethod("SayHi", new Type[] { typeof(string), typeof(string) });
      if (method != null)
      {
          //因为SayHi()方法是一个实例方法,不是静态方法,所以调用SayHi()方法的时候,必须在某个对象上调用,所以method.Invoke() 需要传递一个具体的Person对象进去
          object obj = Activator.CreateInstance(typePerson);//创建一个Person对象
          method.Invoke(obj, new object[] { "张三", "吃了吗" });//调用SayHi(string s1,string s2)重载方法
      }
      else
      {
          Console.WriteLine("找不到你要调用的方法");
      }
      Console.ReadKey();

     

    FieldInfo    获取字段

    1. 1 //获得所有的字段
      2 FieldInfo[] fields = typePerson.GetFields();
      3 //遍历每个字段
      4 for (int i = 0; i < fields.Length; i++)
      5 {
      6         //输出每个字段名
      7     Console.WriteLine(fields[i].Name);
      8 }
      9 Console.ReadKey(); 

     

    EventInfo    获取事件

     





  • 相关阅读:
    第150天:网页中插入百度地图方法(需要密钥)
    第149天:javascript中this的指向详解
    第148天:js+rem动态计算font-size的大小,适配各种手机设备
    第147天:web前端开发中的各种居中总结
    第146天:移动H5前端性能优化
    第145天:jQuery.touchSlider触屏满屏左右滚动幻灯片
    第144天:PS切图方法总结
    第143天:渐进增强和优雅降级之间的不同
    第142天:Size Marks下载安装和使用方法
    第141天:前端开发中浏览器兼容性问题总结(二)
  • 原文地址:https://www.cnblogs.com/pirates/p/4590360.html
Copyright © 2011-2022 走看看