擼·反射

反射是一個程序集發現及運行的過程,經過反射能夠獲得*.exe或*.dll等程序集內部的信息。使用反射能夠看到一個程序集內部的接口、類、方法、字段、屬性、特性等等信息。在System.Reflection命名空間內包含多個反射經常使用的類。如下是基礎

常見反射類html

類型 做用
Assembly 經過此類能夠加載操縱一個程序集,並獲取程序集內部信息
EventInfo 該類保存給定的事件信息
FieldInfo 該類保存給定的字段信息
MethodInfo 該類保存給定的方法信息
MemberInfo 該類是一個基類,它定義了EventInfo、FieldInfo、MethodInfo、PropertyInfo的多個公用行爲
Module 該類可使你能訪問多個程序集中的給定模塊
ParameterInfo 該類保存給定的參數信息      
PropertyInfo 該類保存給定的屬性信息

1、System.Reflection.Assembly類

經過Assembly能夠動態加載程序集,並查看程序集的內部信息,其中最經常使用的就是Load()這個方法。性能

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

利用Assembly的object CreateInstance(string) 方法能夠反射建立一個對象,參數爲類名。spa

2、System.Type類

  Type是最經常使用到的類,經過Type能夠獲得一個類的內部信息,也能夠經過它反射建立一個對象。通常有三個經常使用的方法可獲得Type對象。code

  1. 利用typeof() 獲得Type對象
Type type=typeof(Example);
  1. 利用System.Object.GetType() 獲得Type對象
Example example=new Example();
Type type=example.GetType();
  1. 利用System.Type.GetType() 獲得Type對象
Type type=Type.GetType("MyAssembly.Example",false,true);

注意第一個參數是類名,第二個參數表示若找不到對應類時是否拋出異常,第三個參數表示類名是否區分大小寫。htm

例子:
咱們最多見的是利用反射與Activator結合來建立對象。對象

Assembly assembly= Assembly.Load("MyAssembly");
   Type type=assembly.GetType("Example");
   object obj=Activator.CreateInstance(type);

3、反射方法

  1. 經過 System.Reflection.MethodInfo能查找到類裏面的方法。
    代碼:
Type type=typeof(Example);
    MethodInfo[] listMethodInfo=type.GetMethods();
    foreach(MethodInfo methodInfo in listMethodInfo)
    Cosole.WriteLine("Method name is "+methodInfo.Name);
  1. 咱們也能經過反射方法執行類裏面的方法。
    代碼:
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);  //第二個參數類型爲object[],表明Hello World方法的對應參數,輸入值爲null表明沒有參數。

4、反射屬性

  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);
  1. 咱們也能夠經過如下方法設置或者獲取一個對象的屬性值
    代碼:
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

5、反射字段

經過 System.Reflection.FieldInfo 能查找到類裏面的字段
它包括有兩個經常使用方法SetValue(object ,object )和GetValue(object) 由於使用方法與反射屬性很是類似,在此再也不多做介紹。
(略)blog

6、反射特性

經過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());

7、經常使用實例

  雖然反射有不少奧妙之處,但要注意使用反射生成對象會耗費不少性能,所能必須瞭解反射的特性,在合適的地方使用。最多見例子就是利用單體模式與反射一併使用, 在BLL調用DAL的時候,經過一個反射工廠生成DAL實例。ip

namespace Project.Common
{
    public class Factory
    {
        //記錄dal的對象
        private static Hashtable dals;
        //用assemblyString記錄DAL程序集的全名稱
        private static string assemblyString = ConfigurationManager.AppSettings["LinqDAL"];
        private static Assembly assembly;

        static Factory()
        {
            dals = new Hashtable();
            assembly = Assembly.Load(assemblyString);
        }

        private static object CreateInstance(string typeName)
        {
            //當第一次加載時,將反射對象保存於dals集合裏
            if (!dals.ContainsKey(typeName))
            {
                //建立反射對象
                object object1 = assembly.CreateInstance(typeName);

                if (object1 == null)
                    throw new Exception("未能建立此對象");
                //把對象加入dals集合
                dals["typeName"] = object1;
            }
            return dals["typeName"];
        }

        public static IExampleDAL CreateExampleDAL()
        {
            return (IExampleDAL)CreateInstance(assemblyString + ".ExampleDAL");
        }
    }

     class Program
    {
        //利用工廠模式生成對象
        static void Main(string[] args)
        {
            IExampleDAL iExampleDAL=Factory.CreateExampleDAL();
            Console.ReadKey();
        }
    }
}

namespace Project.IDAL
{
    public interface IExampleDAL
    {
        ///<summary>
        /// 插入Example行,若插入成功,則返回新增Example的行數
        ///</summary>
        ///<param name="example">Example對象</param>
        ///<returns>返回新增Example行數,默認值爲-1</returns>
        int AddExample(Example example);

        ///<summary>
        /// 更新Example表,Update成功返回已經更新的數據條數,失敗返回-1
        ///</summary>
        ///<param name="example">Example對象</param>
        ///<returns>Update成功返回已經更新的數據條數,失敗返回-1</returns>
        int UpdateExample(Example example);

        ///<summary>
        /// 刪除Example表中ID等於exampleID的行,返回已刪除行數
        ///</summary>
        ///<param name="exampleID">Example對象的ID值</param>
        ///<returns>返回刪除行數</returns>
        int DeleteExample(int exampleID);

        ///<summary>
        /// 獲取Example表的全部行
        ///</summary>
        ///<returns>返回Example表中的全部Example對象</returns>
        IList<Example> GetList();

        ///<summary>
        ///  根據ID獲取對應Example對象
        ///</summary>
        ///<param name="id"></param>
        ///<returns></returns>
        Example GetExampleByID(int id);
    }
}

namespace Project.DAL
{
    public class ExampleDAL:IExampleDAL
    {
        public int AddExample(Example example)
        {
             //實現AddExample方法
        }      
    }
}

總結

本篇文章轉載於 風塵浪子的《反射的奧妙

相關文章
相關標籤/搜索