反射+IOC容器

gaibian0823發表於2015-07-31

    說起反射,我們並不陌生,並且我在之前的部落格中,http://blog.csdn.net/gaibian0823/article/details/44624423也已經提到過,一個是這裡面提到的只是理解層面上的,二是反射一般很少自己出現,都是結合著其他知識點出現。所以這次不會再體現在理解層面上,我們從例子中看問題。

一、反射

    反射就是在我們不去引用另外一個程式集或者模組,而直接呼叫他的屬性、方法。

  1.首先是這個程式,我要在Program中呼叫User中的屬性以及方法。

                              

  2.類User中的程式碼:

<span style="font-family:KaiTi_GB2312;font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ITOO_DAL
{
    public class User
    {
        //欄位
        public string Field = "Hello World";

        //屬性
        public string Name { get; set; }

        //無參構造
        public User()
        {
            this.Name = "無參構造";     
        }

        //有參構造
        public User(string UserName)
        {
            this.Name = UserName;
        }

        //public函式
        public void publicFunction()
        {
            Console.WriteLine(string.Format("呼叫的是我public方法"));
        }

        //private函式
        private void privateFunction()
        {
            Console.WriteLine(string.Format("呼叫的是我private方法"));
        }

        //static函式
        public static void staticFunction()
        {
            Console.WriteLine(string.Format("呼叫的是我靜態static方法"));
        }

        //public帶參帶返回值函式
        public string publicFunctionPara(string UserName)
        {
            return string.Format("呼叫帶參帶返回值函式,引數為:{0}",UserName);
        }
    }
}
</span>
 3.主函式

<span style="font-family:KaiTi_GB2312;font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ITOO_Reflection
{
    class Program
    {
        static void Main(string[] args)
        {
            //使用 Assembly 定義和載入程式集,
            //載入在程式集清單中列出的模組,
            //以及從此程式集中查詢型別並建立該型別的例項.
            //獲取程式集
            Assembly assembly = Assembly.Load("ITOO_DAL");

            //從程式集中獲取指定物件型別;
            Type type = assembly.GetType("ITOO_DAL.User");

            //方法一:建立類的例項 

           //使用Activator建立例項(無引數建構函式)
            var userNoParameter = Activator.CreateInstance(type);

            //使用Activator建立例項(帶引數建構函式)
            var userParameter = Activator.CreateInstance(type, "wangjinbo");
  
            //方法二:建立類的例項

            //使用無參建構函式建立類(先反射建立建構函式,再使用建構函式建立類)
            ConstructorInfo constructorNoParameter = type.GetConstructor(new Type[] { });
            var userNoParameterByConstructorInfo = constructorNoParameter.Invoke(new object[] { });

            //使用有參建構函式建立類(先反射建立建構函式,再使用建構函式建立類) 
            ConstructorInfo constructorParameter = type.GetConstructor(new Type[] { typeof(string) });
            var userParameterByConstructorInfo = constructorParameter.Invoke(new object[] { "wangjinbo" });

            //呼叫public函式(無引數)
            type.InvokeMember("publicFunction",
                              BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, userNoParameter,
                              null);

            //呼叫public函式(帶引數)
            string returnValuePublic =
                type.InvokeMember("publicFunctionPara",
                                  BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding, null, userNoParameter,
                                  new object[] { "wangjinbo" }) as string;
            Console.WriteLine(returnValuePublic);

            //呼叫靜態方法       
            string returnValueStatic =
                type.InvokeMember("staticFunction", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
                                  null, null, new object[] { }) as string;
            Console.WriteLine(returnValueStatic);

            //反射屬性
            var Name =
                type.InvokeMember("Name", BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance, null,
                                  userNoParameter, new object[] { }) as string;
            Console.WriteLine(Name);

            //設定屬性(設定Name屬性為"NewName")
            type.InvokeMember("Name", BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null,
                                  userNoParameter, new object[] { "NewName" });


            //反射欄位
            string Field =
                type.InvokeMember("Field", BindingFlags.GetField | BindingFlags.Public | BindingFlags.Instance, null,
                                  userNoParameter, new object[] { }) as string;
            Console.WriteLine(Field);

            //設定欄位(設定Field欄位為"NewField")
            type.InvokeMember("Field", BindingFlags.SetField | BindingFlags.Public | BindingFlags.Instance, null,
                                  userNoParameter, new object[] { "NewField" });

        }
    }
}
</span>
   上面就是通過反射從一個類中呼叫了另一個類中的屬性以及方法。

二、反射+IOC容器

    1.什麼是IOC?

    IOC即控制反轉(Inversion of Control,英文縮寫為IoC)是一個重要的物件導向程式設計的法則來削減計算機程式的耦合問題,也是輕量級的Spring框架的核心。 控制反轉一般分為兩種型別,依賴注入(Dependency Injection,簡稱DI)和依賴查詢(Dependency Lookup)。依賴注入應用比較廣泛。

    當然這是官方解釋,我的解釋是:不建立物件,但是描述建立它們的方式。在程式碼中不直接與物件和服務連線,但在配置檔案中描述哪一個元件需要哪一項服務。容器負責將這些聯絡在一起。簡單的來講,就是由容器控制程式之間的關係,而非傳統實現中,由程式程式碼直接操控。這也就是所謂“控制反轉”的概念所在:控制權由應用程式碼中轉到了外部容器,控制權的轉移,是所謂反轉。

    2.反射+依賴注入、依賴查詢

    首先,我們來看依賴注入:

    配置檔案中     

    通過get,set注入

 

    然後直接使用D層所有方法:

 

   2.依賴查詢

   配置檔案中:

 

    程式中,GetObject為反射:

 

    依賴注入和依賴查詢都用到了反射,但是依賴注入是被動的,依賴查詢是主動的,依賴查詢是需要來把配置檔案中的id寫進來,而注入get,set後,可以使用裡面的所有方法。

    總的流程就是:

    1.載入配置檔案中的所有內容。

    2.將id,value放到一個雜湊表中。

    3.反射來查詢id或者name,來呼叫相關類。

    這些知識,我們用了很長時間,但是前面並不理解,所以我們需要更加主動地去整理總結這些知識,而不是被動地接受。

相關文章