基礎拾遺------反射詳解

基礎拾憶:

基礎拾遺------特性詳解html

基礎拾遺------webservice詳解程序員

基礎拾遺------redis詳解web

基礎拾遺------反射詳解redis

基礎拾遺------委託詳解json

基礎拾遺------接口詳解設計模式

基礎拾遺------泛型詳解數組

基礎拾遺-----依賴注入框架

基礎拾遺-----數據註解與驗證ide

基礎拾遺-----mongoDB操做函數

基礎拾遺----RabbitMQ

前言

MSDN定義:經過 System.Reflection 命名空間中的類以及 System.Type,您能夠獲取有關已加載的程序集和在其中定義的類型(如類、接口和值類型)的信息。 您也能夠使用反射在運行時建立類型實例,以及調用和訪問這些實例。

這句話能夠看出反射的命名空間是System.ReflectionSystem.Type.主要功能是在已經加載的程序集裏獲取接口、類、方法、字段、屬性、特性等類型信息,

1.反射優缺點

1.1.優勢:

  一、反射提升了程序的靈活性和擴展性。

  二、下降耦合性,提升自適應能力。

  三、它容許程序建立和控制任何類的對象,無需提早硬編碼目標類。

1.2.缺點: 

  一、性能問題:使用發射基本上是一種解釋操做,用於字段和方法接入時要遠慢於直接代碼。所以反射機制主要應用在對靈活性和拓展性要求很高的系統框架上,普通程序不建議使用。

  二、使用反射會模糊程序內部邏輯;程序員但願在源代碼中看到程序的邏輯,反射卻繞過了源代碼的技術,於是會帶來維護的問題,反射代碼比相應的直接代碼更復雜。

層次結構

2.System.reflection命名空間

2.1包含的類以下:

  Assembly 定義和加載程序集,加載在程序集清單中列出的模塊,以及今後程序集中查找類型並建立該類型的實例。

  Module 瞭解以下的相似信息:包含模塊的程序集以及模塊中的類等。您還能夠獲取在模塊上定義的全部全局方法或其餘特定的非全局方法。

  ConstructorInfo 瞭解以下的相似信息:構造函數的名稱、參數、訪問修飾符(如 public 或 private)和實現詳細信息(如 abstract 或 virtual)等。

  System.Type 的 GetConstructors 或 GetConstructor 方法來調用特定的構造函數。

  MethodInfo 來了解以下的相似信息:方法的名稱、返回類型、參數、訪問修飾符(如 public 或 private)和實現詳細信 息(如 abstract 或 virtual)等。使用 Type 的      GetMethods 或 GetMethod 方法來調用特定的方法。

  FieldInfo 來了解以下的相似信息:字段的名稱、訪問修飾符(如 public 或 private)和實現詳細信息(如 static)等;並獲取或設置字段值。

  EventInfo 來了解以下的相似信息:事件的名稱、事件處理程序數據類型、自定義屬性、聲明類型和反射類型等;並添加或移除事件處理程序。

  PropertyInfo 來了解以下的相似信息:屬性的名稱、數據類型、聲明類型、反射類型和只讀或可寫狀態等;並獲取或設置屬性值。

  ParameterInfo 來了解以下的相似信息:參數的名稱、數據類型、參數是輸入參數仍是輸出參數,以及參數在方法簽名中的位置等。

3.命名空間System.Type

3.1.Type類的屬性:

 Name 數據類型名

FullName 數據類型的徹底限定名(包括命名空間名)

Namespace 定義數據類型的命名空間名

IsAbstract 指示該類型是不是抽象類型

IsArray   指示該類型是不是數組

IsClass   指示該類型是不是類

IsEnum   指示該類型是不是枚舉

IsInterface    指示該類型是不是接口

IsPublic 指示該類型是不是公有的

IsSealed 指示該類型是不是密封類

IsValueType 指示該類型是不是值類型

3.2 Type類的方法:

GetConstructor(), GetConstructors():返回ConstructorInfo類型,用於取得該類的構造函數的信息

GetEvent(), GetEvents():返回EventInfo類型,用於取得該類的事件的信息

GetField(), GetFields():返回FieldInfo類型,用於取得該類的字段(成員變量)的信息

GetInterface(), GetInterfaces():返回InterfaceInfo類型,用於取得該類實現的接口的信息

GetMember(), GetMembers():返回MemberInfo類型,用於取得該類的全部成員的信息

GetMethod(), GetMethods():返回MethodInfo類型,用於取得該類的方法的信息

GetProperty(), GetProperties():返回PropertyInfo類型,用於取得該類的屬性的信息     能夠調用這些成員,其方式是調用Type的InvokeMember()方法,或者調用     MethodInfo, PropertyInfo和其餘類的Invoke()方法。

4.具體用法

4.一、假設你要反射一個 DLL 中的類,而且沒有引用它(即未知的類型): 

Assembly assembly = Assembly.LoadFile("程序集路徑,即物理路徑"); // 加載程序集(EXE 或 DLL) 
object obj = assembly.CreateInstance("類的徹底限定名,即包括命名空間"); // 建立類的實例 

4.二、若要反射當前項目中的類(即當前項目已經引用它了)能夠爲:

Assembly assembly = Assembly.GetExecutingAssembly(); // 獲取當前程序集 
object obj = assembly.CreateInstance("類的徹底限定名,即包括命名空間"); // 建立類的實例,返回爲 object 類型,須要強制類型轉換

4.三、二者結合:

Type type = Type.GetType("類的徹底限定名"); 
object obj = type.Assembly.CreateInstance(type);

5.實例

5.一、建立對象實例

    /// <summary>
    /// 反射幫助類
    /// </summary>
    public static class ReflectionHelper
    {
        /// <summary>
        /// 建立對象實例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fullName">命名空間.類型名</param>
        /// <param name="assemblyName">程序集</param>
        /// <returns></returns>
        public static T CreateInstance<T>(string fullName, string assemblyName)
        {
            string path = fullName + "." + assemblyName;//命名空間.類型名,程序集
            Type o = Type.GetType(path);//加載類型
            object obj = Activator.CreateInstance(o, true);//根據類型建立實例
            return (T)obj;//類型轉換並返回
        }

        /// <summary>
        /// 建立對象實例
        /// </summary>
        /// <typeparam name="T">要建立對象的類型</typeparam>
        /// <param name="assemblyName">類型所在程序集名稱</param>
        /// <param name="nameSpace">類型所在命名空間</param>
        /// <param name="className">類型名</param>
        /// <returns></returns>
        public static T CreateInstance<T>(string assemblyName, string nameSpace, string className)
        {
            try
            {
                string fullName = nameSpace + "." + className;//命名空間.類型名
                //此爲第一種寫法
                object ect = Assembly.Load(assemblyName).CreateInstance(fullName);//加載程序集,建立程序集裏面的 命名空間.類型名 實例
                return (T)ect;//類型轉換並返回
                //下面是第二種寫法
                //string path = fullName + "," + assemblyName;//命名空間.類型名,程序集
                //Type o = Type.GetType(path);//加載類型
                //object obj = Activator.CreateInstance(o, true);//根據類型建立實例
                //return (T)obj;//類型轉換並返回
            }
            catch
            {
                //發生異常,返回類型的默認值
                return default(T);
            }
        }
    }

5.二、調用方法實例

  public void reflectTest()
        {
            System.Reflection.Assembly ass;
            Type type;
            object obj;
            try
            {
                ass = System.Reflection.Assembly.LoadFile(@"d:\ReflectWyl.dll");
                type = ass.GetType("WebTest.ReflectTest");//必須使用名稱空間+類名稱
                System.Reflection.MethodInfo method = type.GetMethod("WriteString");//方法的名稱
                obj = ass.CreateInstance("WebTest.ReflectTest");//必須使用名稱空間+類名稱
                string s = (string)method.Invoke(obj, new string[] { "Wangyanling" }); //實例方法的調用

                //靜態方法的調用
                method = type.GetMethod("WriteName");//方法的名稱
                s = (string)method.Invoke(null, new string[] { "Wangyanling" });
                //無參數的實例方法
                method = type.GetMethod("WriteNoPara");
                s = (string)method.Invoke(obj, null);
                // Response.Write(s+"<br>");
                method = null;
            }
            catch (Exception ex)
            {
               
            }
            finally
            {
                ass = null;
                type = null;
                obj = null;
            }
        }

5.三、對象轉換爲Json

對象進行反序列化咱們應該在項目中或多火燒都有遇到過,在這當中也是用到了反射不知道,您有沒有注意過。如今把對象轉爲json的實現貼出來,你們根據代碼在瞭解一下反射。

  /// <summary> 
        /// 對象轉換爲Json 
        /// </summary> 
        /// <param name="jsonObject">對象</param> 
        /// <returns>Json字符串</returns> 
        public static string ToJson(object jsonObject)
        {
            string jsonString = "{";
            PropertyInfo[] propertyInfo = jsonObject.GetType().GetProperties();
            for (int i = 0; i < propertyInfo.Length; i++)
            {
                object objectValue = propertyInfo[i].GetGetMethod().Invoke(jsonObject, null);
                string value = string.Empty;
                if (objectValue is DateTime || objectValue is Guid || objectValue is TimeSpan)
                {
                    value = "'" + objectValue.ToString() + "'";
                }
                else if (objectValue is string)
                {
                    value = "'" + ToJson(objectValue.ToString()) + "'";
                }
                else if (objectValue is IEnumerable)
                {
                    value = ToJson((IEnumerable)objectValue);
                }
                else
                {
                    value = ToJson(objectValue.ToString());
                }
                jsonString += "\"" + ToJson(propertyInfo[i].Name) + "\":" + value + ",";
            }
            jsonString.Remove(jsonString.Length - 1, jsonString.Length);
            return jsonString + "}";
        }
View Code

5.四、工廠模式

設計模式小提示:

    簡單工廠:簡單實用,但違反開放封閉;
        工廠方法:開放封閉,單一產品;
        抽象工廠:開放封閉,多個產品;
       反射工廠:能夠最大限度的解耦。

下面一個例子就是用反射實現工廠模式

namespace FactoryPartern
{
    public interface IFactoryOrg
    {
        IOrg CreateOrg();
    }

    public class FactoryA : IFactoryOrg
    {
        public IOrg CreateVehicle()
        {
            return new A();
        }
    }
    public class FactoryB : IFactoryOrg
    {
        public IOrg CreateVehicle()
        {
            return new B();
        }
    }
    public interface IOrg
    {
        void go();
    }
    public class A : IOrg
    {
        public void go()
        {
            //
        }
    }
    public class B : IOrg
    {
        public void go()
        {
            //
        }
    }
    class ReflectFactory
    {
        public static IOrg CreateOrgByReflect(string typeName)
        {
            string namespaceStr = "FactoryPartern";
            string tempChar = ".";
            //注意使用Type.GetType(String classname)時,必須指定其命名空間,不然返回爲null
            Type type = Type.GetType(namespaceStr + tempChar + typeName, true);

            ConstructorInfo ci = type.GetConstructor(System.Type.EmptyTypes);
            return (IOrg)ci.Invoke(null);
        }
    }
}

進行調用

IOrg org= ReflectFactory.CreateOrgByReflect("A");
           org.go();

以上舉得一些簡單的例子用來幫助理解,若是有什麼不足的地方歡迎拍磚。也能夠QQ與我聯繫。

相關文章
相關標籤/搜索