• 反射整理学习<一>


    前言:    

    由于身边也没什么学习资料,也就一边利用网络一边自己理解整理,慢慢地步入神秘的反射机制。

     

     

     

        反射提供了封装程序集、模块和类型的对象(Type 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。

    • 简而言之, 反射机制指的是程序在运行时能够获取自身的信息。例如一个对象能够在运行时知道自己有哪些方法和属性。

     

     

     

    • 使用 Assembly 定义和加载程序集,加载在程序集清单中列出的模块,以及从此程序集中查找类型并创建该类型的实例。

    • 使用 Module 发现以下信息:包含模块的程序集以及模块中的类等。您还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。

    • 使用 ConstructorInfo 发现以下信息:构造函数的名称、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。使用 TypeGetConstructorsGetConstructor 方法来调用特定的构造函数。

    • 使用 MethodInfo 发现以下信息:方法的名称、返回类型、参数、访问修饰符(如 public 或 private)和实现详细信息(如 abstract 或 virtual)等。使用 TypeGetMethodsGetMethod 方法来调用特定的方法。

    • 使用 FieldInfo 发现以下信息:字段的名称、访问修饰符(如 public 或 private)和实现详细信息(如 static)等;并获取或设置字段值。

    • 使用 EventInfo 发现以下信息:事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等;并添加或移除事件处理程序。

    • 使用 PropertyInfo 发现以下信息:属性的名称、数据类型、声明类型、反射类型和只读或可写状态等;并获取或设置属性值。

    • 使用 ParameterInfo 发现以下信息:参数的名称、数据类型、参数是输入参数还是输出参数,以及参数在方法签名中的位置等。

    • 当您在一个应用程序域的仅反射上下文中工作时,请使用 CustomAttributeData 来了解有关自定义属性的信息。使用 CustomAttributeData,您不必创建属性的实例就可以检查它们。

    •  

      程序集,模块,类型,成员之间的关系(这里我做一简要说明)

      程序集是.NET框架应用程序的构造块,程序集构成部署,版本控制,重复使用,激活范围控制和安全权限的基本单元。

      直接说重点:程序集包含模块,而模块包含类型,类型有包含成员。

       

       

       

       

          我们承接上面的内容,System.Reflection这个命名空间下定义了一系列的类,他们与System.Type类一起提供反射功能。看完这一句话你应该明白了,System.Reflection命名空间下的一系列的类和System命名空间下的Type类是一起提供了反射功能,缺一不可。于是我们实现反射功能,为什么会至少会引用以下两个命名空间:

       

       

       

      现在我们来看一下System.Reflection命名空间下的主要类的功能:(下面列举几个常用的)

      Assembly 表示一个程序集,它是一个可重用、无版本冲突并且可自我描述的公共语言运行时应用程序构造块。 
      Module  在模块上执行反射。
      ConstructorInfo 发现类构造函数的特性并提供对构造函数元数据的访问权。
      MethodInfo 发现方法的特性并提供对方法元数据的访问。
      FieldInfo 发现字段特性并提供对字段元数据的访问权。
      PropertyInfo 发现属性的特性并提供对属性元数据的访问。
      CustomAttributeData 提供对加载到只反射上下文中的程序集、模块、类型、成员和参数的自定义特性数据的访问。
       EventInfo  发现事件的特性并提供对事件元数据的访问权。

       

      System.Reflection.Emit 命名空间的类提供了一种特殊形式的反射,使您能够在运行时生成类型。

      反射也可用于创建称作类型浏览器的应用程序,它使用户能够选择类型,然后查看有关选定类型的信息。

       

      System.Reflection 命名空间中的类最常用的方法都使用统一的模式。Module,TypeMemberInfo类的成员都具有如下基本形式:

    • MyInstance[]FindXxx(filter,filterCriteria):查找并返回经过筛选的类型列表,或者在当前类型没有实现任何匹配筛选器的类型的情况下返回空数组。
    • MyInstance GetXxx(<parameters>):返回由<parameters>唯一指定的类型,如果不存在这样的类型,成员将返回一个空引用。
    • MyInstance[]GetXxxs():返回所有的公共类型,如果不存在公共类型,成员将返回空数组。
    • MyInstance[]GetXxxs(<parameters>):返回由<parameters>指定的所有类型,如果不存在这样的类型,成员将返回空数组

    •  


       

      Type类为System.Refection 实现反射功能的基础,也是访问程序集的元数据的主要方式。

      对于Type类我们先熟悉一下它提供了那些属性和方法,当然用法很简单,我们看完它的内容就小小的测试一下:

      具体的可以在MSDN自己看:http://msdn.microsoft.com/zh-cn/library/42892f65.aspx

      泛型类型定义不可以从封闭构造的类型赋值。也就是说,不能将封闭构造类型MyGenericList<int>赋给MyGenericList<T>类型的变量。

      下面是我的测试代码:

      TyepTest Code
       1 using System;
       2 using System.Reflection;
       3 
       4 namespace TypeInfoTest
       5 {
       6      public class Program
       7     {
       8         static void Main(string[] args)
       9         {
      10             GetTypeInfo(" TypeInfoTest.Program");
      11             Console.ReadKey();
      12         }
      13 
      14         private static void GetTypeInfo(string className)
      15         {
      16             try
      17             {
      18                 Type type = Type.GetType(className);
      19                 Console.WriteLine("类型名:" + type.Name);
      20                 Console.WriteLine("类的全名:" + type.FullName);
      21                 Console.WriteLine("命名空间名:" + type.Namespace);
      22                 Console.WriteLine("程序集名:" + type.Assembly);
      23                 Console.WriteLine("模块名:" + type.Module);
      24                 Console.WriteLine("基类名" + type.BaseType);
      25                 Console.WriteLine("运行时映射类名:" + type.UnderlyingSystemType);
      26                 Console.WriteLine("是否是类:" + type.IsClass);
      27                 Console.WriteLine("是否是从COM类型库导入的:"+type.IsImport);//是否应用了ComImportAttribute属性
      28                 Console.WriteLine("是否是泛型类型:"+type.IsGenericType);
      29                 Console.WriteLine("是否是接口:" + type.IsInterface);
      30                 Console.WriteLine("是否是抽象类:" + type.IsAbstract);
      31                 Console.WriteLine("是否是数组类:" + type.IsArray);
      32                 Console.WriteLine("是否是值类型:" + type.IsValueType);
      33                 Console.WriteLine("是否是基本类型:" + type.IsPrimitive);
      34                 Console.WriteLine("是否是公共类型:"+type.IsPublic);
      35                 Console.WriteLine("关联的属性:"+type.Attributes);
      36                 Console.WriteLine("句柄:"+type.TypeHandle);
      37                 Console.WriteLine("===============MakeArrayType=================");
      38                 Type t = typeof(Program).MakeArrayType();
      39                 Console.WriteLine("Program类型的数组: {0}", t);
      40                 t = typeof(Program).MakeArrayType(2);
      41                 Console.WriteLine("Program类型的数组: {0}", t);
      42                 try
      43                 {
      44                     t = typeof(Program).MakeArrayType(-1);
      45                 }
      46                 catch (Exception ex)
      47                 {
      48                     Console.WriteLine("{0}", ex);
      49                 }
      50                 Console.WriteLine("===============MakeArrayType=================");
      51                 Console.WriteLine("\n===============.GetMethods=================");
      52                 MethodInfo[] Minfos = typeof(Program).GetMethods();
      53                 foreach (MethodInfo i in Minfos)
      54                 {
      55                     Console.WriteLine(i.Name);
      56                 }
      57                 Console.WriteLine("===============.GetMethods=================\n");
      58                 #region "类的公共成员"
      59                 Console.WriteLine("类的公共成员:");
      60                 foreach (MemberInfo info in type.GetMembers())
      61                 {
      62                     Console.WriteLine("\t{0} :{1}", info.MemberType, info);
      63                 } 
      64                 #endregion
      65                 #region "类的字段成员"
      66                 Console.WriteLine("\t类的字段成员:");
      67                 if (type.GetFields().Length > 0)
      68                 {
      69                     foreach (FieldInfo field in type.GetFields())
      70                     {
      71                         Console.WriteLine("\t{0} :{1}", field.MemberType, field);
      72                     }
      73                 }
      74                 else
      75                 {
      76                     Console.WriteLine("该类型不包含字段!");
      77                 }
      78                 #endregion
      79             }
      80             catch (Exception ex)
      81             {
      82 
      83                 Console.WriteLine(ex.Message);
      84             }
      85         }
      86     }
      87 }

      运行结果:

           

  • 相关阅读:
    Socket和数据库的一些使用---郭雪彬
    懒加载--初步理解. by:王朋
    自定义带图片和文字的Button的排版--陈棚
    一些开源库分享 ---严焕培
    实现“手机qq”侧滑菜单 -- 吴欧
    iOS 小技巧总结
    Responder一点也不神秘————iOS用户响应者链完全剖析 周傅琦君
    通过版本号来判断用户是否是第一次登陆----By张秀清
    常用第三方推荐
    static, const 和 static const 变量的初始化问题
  • 原文地址:https://www.cnblogs.com/rohelm/p/2470808.html
Copyright © 2020-2023  润新知