• 反射的奥妙 (转)


    摘自:http://www.cnblogs.com/leslies2/archive/2011/11/22/2257703.html

    反射是一个程序集发现及运行的过程,通过反射可以得到*.exe或*.dll等程序集内部的信息。使用反射可以看到一个程序集内部的接口、类、方法、字段、属性、特性等等信息。在System.Reflection命名空间内包含多个反射常用的类,下面表格列出了常用的几个类。

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

    一、System.Reflection.Assembly类

         通过Assembly可以动态加载程序集,并查看程序集的内部信息,其中最常用的就是Load()这个方法。

         Assembly assembly=Assembly.Load("MyAssembly");

         利用Assembly的object CreateInstance(string) 方法可以反射创建一个对象,参数0为类名。

    二、System.Type类

         Type是最常用到的类,通过Type可以得到一个类的内部信息,也可以通过它反射创建一个对象。一般有三个常用的方法可得到Type对象。

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

      Type type=typeof(Example);

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

      Example example=new Example();

      Type type=example.GetType();

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

      Type type=Type.GetType("MyAssembly.Example",false,true);

      注意参数0是类名,参数1表示若找不到对应类时是否抛出异常,参数1表示类名是否区分大小写

       例子:

       我们最常见的是利用反射与Activator结合来创建对象。

       Assembly assembly= Assembly.Load("MyAssembly");

       Type type=assembly.GetType("Example");

       object obj=Activator.CreateInstance(type);

        

    三、反射方法

        1.通过 System.Reflection.MethodInfo能查找到类里面的方法

        代码:

        Type type=typeof(Example);

        MethodInfo[] listMethodInfo=type.GetMethods();

        foreach(MethodInfo methodInfo in listMethodInfo)

             Cosole.WriteLine("Method name is "+methodInfo.Name);

      

       2.我们也能通过反射方法执行类里面的方法

       代码:

       Assembly assembly= Assembly.Load("MyAssembly");

       Type type=assembly.GetType("Example");

       object obj=Activator.CreateInstance(type);

       MethodInfo methodInfo=type.GetMethod("Hello World");  //根据方法名获取MethodInfo对象

       methodInfo.Invoke(obj,null);  //参数1类型为object[],代表Hello World方法的对应参数,输入值为null代表没有参数

    四、反射属性

       1.通过 System.Reflection.PropertyInfo 能查找到类里面的属性

         常用的方法有GetValue(object,object[]) 获取属性值和 SetValue(object,object,object[]) 设置属性值

       代码:

        Type type=typeof(Example);

        PropertyInfo[] listPropertyInfo=type.GetProperties();

        foreach(PropertyInfo propertyInfo in listPropertyInfo)

             Cosole.WriteLine("Property name is "+ propertyInfo.Name);

       

       2.我们也可以通过以下方法设置或者获取一个对象的属性值

       代码:

       Assembly assembly=Assembly.Load("MyAssembly");

       Type type=assembly.GetType("Example");

       object obj=Activator.CreateInstance(type);

       PropertyInfo propertyInfo=obj.GetProperty("Name");    //获取Name属性对象

       var name=propertyInfo.GetValue(obj,null);                //获取Name属性的值

       PropertyInfo propertyInfo2=obj.GetProperty("Age");     //获取Age属性对象

       propertyInfo.SetValue(obj,34,null);                              //把Age属性设置为34

    五、反射字段

        通过 System.Reflection.FieldInfo 能查找到类里面的字段

        它包括有两个常用方法SetValue(object ,object )和GetValue(object)  因为使用方法与反射属性非常相似,在此不再多作介绍

       (略)

    六、反射特性

       通过System.Reflection.MemberInfo的GetCustomAttributes(Type,bool)就可反射出一个类里面的特性,以下例子可以反射出一个类的所有特性

       代码:

       Type type=typeof("Example");

       object[] typeAttributes=type.GetCustomAttributes(false);       //获取Example类的特性

       foreach(object attribute in typeAttributes)

             Console.WriteLine("Attributes description is "+attribute.ToString());

      

       通过下面例子,可以获取Example类Name属性的所有特性

       代码:

       public class Example

       {

             [DataMemberAttribute]

             publics string Name

              {get;set;}

            ..................

        }

        Type type = typeof(Example);            PropertyInfo propertyInfo=type.GetProperty("Name");    //获取Example类的Name属性     foreach (object attribute in propertyInfo.GetCustomAttributes(false))        //遍历Name属性的所有特性            Console.WriteLine(“Property attribute: "+attribute.ToString());

    七、常用实例

     虽然反射有很多奥妙之处,但要注意使用反射生成对象会耗费很多性能,所能必须了解反射的特性,在合适的地方使用。最常见例子就是利用单体模式与反射一并使用,  在BLL调用DAL的时候,通过一个反射工厂生成DAL实例。

      

      1 namespace Project.Common
      2 {
      3     public class Factory
      4     {
      5         //记录dal的对象
      6         private static Hashtable dals;
      7         //用assemblyString记录DAL程序集的全名称
      8         private static string assemblyString = ConfigurationManager.AppSettings["LinqDAL"];
      9         private static Assembly assembly;
     10 
     11         static Factory()
     12         {
     13             dals = new Hashtable();
     14             assembly = Assembly.Load(assemblyString);
     15         }
     16 
     17         private static object CreateInstance(string typeName)
     18         {
     19             //当第一次加载时,将反射对象保存于dals集合里
     20             if (!dals.ContainsKey(typeName))
     21             {
     22                 //创建反射对象
     23                 object object1 = assembly.CreateInstance(typeName);
     24 
     25                 if (object1 == null)
     26                     throw new Exception("未能创建此对象");
     27                 //把对象加入dals集合
     28                 dals["typeName"] = object1;
     29             }
     30             return dals["typeName"];
     31         }
     32 
     33         public static IExampleDAL CreateExampleDAL()
     34         {
     35             return (IExampleDAL)CreateInstance(assemblyString + ".ExampleDAL");
     36         }
     37     }
     38 
     39      class Program
     40     {
     41         //利用工厂模式生成对象
     42         static void Main(string[] args)
     43         {
     44             IExampleDAL iExampleDAL=Factory.CreateExampleDAL();
     45             .................
     46             Console.ReadKey();
     47         }
     48     }
     49 }
     50 
     51 namespace Project.IDAL
     52 {
     53     public interface IExampleDAL
     54     {
     55         ///<summary>
     56         /// 插入Example行,若插入成功,则返回新增Example的行数
     57         ///</summary>
     58         ///<param name="example">Example对象</param>
     59         ///<returns>返回新增Example行数,默认值为-1</returns>
     60         int AddExample(Example example);
     61 
     62         ///<summary>
     63         /// 更新Example表,Update成功返回已经更新的数据条数,失败返回-1
     64         ///</summary>
     65         ///<param name="example">Example对象</param>
     66         ///<returns>Update成功返回已经更新的数据条数,失败返回-1</returns>
     67         int UpdateExample(Example example);
     68 
     69         ///<summary>
     70         /// 删除Example表中ID等于exampleID的行,返回已删除行数
     71         ///</summary>
     72         ///<param name="exampleID">Example对象的ID值</param>
     73         ///<returns>返回删除行数</returns>
     74         int DeleteExample(int exampleID);
     75 
     76         ///<summary>
     77         /// 获取Example表的所有行
     78         ///</summary>
     79         ///<returns>返回Example表中的所有Example对象</returns>
     80         IList<Example> GetList();
     81 
     82         ///<summary>
     83         ///  根据ID获取对应Example对象
     84         ///</summary>
     85         ///<param name="id"></param>
     86         ///<returns></returns>
     87         Example GetExampleByID(int id);
     88     }
     89 }
     90 
     91 namespace Project.DAL
     92 {
     93     public class ExampleDAL:IExampleDAL
     94     {
     95         public int AddExample(Example example)
     96         {
     97              //实现AddExample方法
     98              ...........................
     99         }
    100         ..................................
    101         ..................................
    102     }
    103 }
  • 相关阅读:
    String,StringBuffer与StringBuilder的区别??
    Android之NDK开发的简单实例
    Eclipse在线安装插件奇慢的解决办法
    Android之Windows下生成动态库so并打包到APK中
    Android打包之Ant多渠道打包的实现
    Android打包之Ant打入第三方jar包及zipalign对齐优化
    Android打包之将bat脚本转换成ant脚本
    Android打包之bat脚本打包
    利用ant和dedex解析classes.dex
    Ant详解(用Ant实现Java项目的自动构建和部署)
  • 原文地址:https://www.cnblogs.com/KeenLeung/p/3834931.html
Copyright © 2020-2023  润新知