你(ni)必須要知道的架構知識(shi)~第(di)五章(zhang) 依賴住(zhu)入在這(zhe)個時候出場(chang)了
這段時間(jian)確(que)實忙,以(yi)至(zhi)于連寫(xie)博客的時間(jian)都沒有(you)了,今天正好有(you)點(dian)時間(jian),有(you)第五章依賴(lai)住入(ru)簡單的說(shuo)一下(xia),主(zhu)要分兩塊,一是(shi)依賴(lai)住入(ru)的概念,什么時候使(shi)用依賴(lai)注入(ru),第二個(ge)問題是(shi)通過一個(ge)使(shi)用Unity的實例來讓大家對依賴(lai)注入(ru)有(you)一個(ge)很直(zhi)觀(guan)的認識。
一(yi) 概念:依賴注入,即Dependency Injection,即DI,有(you)時也(ye)叫它控制(zhi)反(fan)轉(zhuan),一(yi)般用IoC來實(shi)(shi)現對象的創(chuang)(chuang)建工作(zuo)(zuo),我(wo)們(men)知道一(yi)個類(lei),要想被實(shi)(shi)例化我(wo)們(men)可(ke)以用new關(guan)鍵字,例如一(yi)個數(shu)據操(cao)(cao)作(zuo)(zuo)接(jie)口(kou)規范interface IRepository{},其中有(you)一(yi)個SQLSERVER的數(shu)據操(cao)(cao)作(zuo)(zuo)去實(shi)(shi)現了(le)它class SQLRepository:IRepository{},而(er)客戶電腦上裝的是oracle,所以沒辦法,我(wo)又為oracle實(shi)(shi)現了(le)一(yi)個數(shu)據操(cao)(cao)作(zuo)(zuo),即class ORACLERepository:IRepository{},如果我(wo)們(men)希望創(chuang)(chuang)建一(yi)個SQLRepository實(shi)(shi)例,我(wo)們(men)可(ke)以有(you)至少(shao)兩種方法,即:
SQLRepository sqlRepository=new SQLRepository();
IRepository iRepository =new SQLRepository();
從上面(mian)兩種(zhong)創(chuang)建對(dui)象的(de)方(fang)法可(ke)以(yi)(yi)知道第二次更面(mian)向對(dui)象,因為iRepository 不僅(jin)可(ke)以(yi)(yi)生成(cheng)SQLRepository對(dui)象,它(ta)還可(ke)以(yi)(yi)生成(cheng)所(suo)有繼承自(zi)IRepository 的(de)對(dui)象,但如果我(wo)們(men)希望在程序運行中,或(huo)者在今天很方(fang)便的(de)是實(shi)現SQLRepository與ORACLERepository之(zhi)間的(de)切換(huan),那需要對(dui)程序進行很大(da)的(de)手術,這事實(shi)上就是類的(de)高(gao)耦合,為了(le)解決上面(mian)的(de)問題(ti),我(wo)們(men)引入(ru)了(le)一種(zhong)在程序”運行時”動(dong)態改變對(dui)象創(chuang)建方(fang)式的(de)技(ji)(ji)術,這種(zhong)技(ji)(ji)術我(wo)們(men)成(cheng)為“控制反(fan)轉”,也就是依賴(lai)注入(ru),目前(qian)比較流行的(de)IoC容器(qi)有Unity,Pico Containe,JBos等,我(wo)們(men)以(yi)(yi)Unity為例來學習一下依賴(lai)注入(ru)在項(xiang)目中的(de)應用。
二 依賴(lai)注入在項目中的(de)應用
我(wo)們看到,這(zhe)就是(shi)一(yi)個依賴注入的(de)項目,它一(yi)般在(zai)(zai)項目中(zhong)是(shi)對所(suo)有層可見的(de),在(zai)(zai)這(zhe)個項目中(zhong),我(wo)們的(de)Service(BLL)層通(tong)過Ioc容(rong)器實現了對Data(DAL)層的(de)控制反轉(zhuan),它將需要實現IoC的(de)類放在(zai)(zai)配置文件中(zhong),這(zhe)樣在(zai)(zai)程序運行時(shi)可以(yi)動態的(de)隨時(shi)調(diao)整。
我(wo)們看到,它會在配置文件中(zhong)找到repositoryContainer這個節點,然后把(ba)它的值取出(chu)并(bing)反射成我(wo)們的對象,下(xia)面(mian)是配置文件中(zhong)的代碼片斷
<configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=1.1.0.0,Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> <section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </configSections> <unity> <containers> <container name="repositoryContainer"> <types> <type type="TESTWEB.Controllers.IPeople,TESTWEB" mapTo="TESTWEB.Controllers.PeopleChina,TESTWEB"></type> </types> </container> </containers> </unity> 以(yi)下(xia)是(shi)實(shi)現Unity依賴注入的DLL
事實上,依賴注入并不神秘,只(zhi)要我們知道(dao)什么時(shi)候(hou)用它,這是最重要的。
下面(mian)分(fen)享(xiang)一(yi)個創(chuang)建(jian)unity容(rong)器的(de)代碼片(pian)斷
/// <summary> /// Initializes container. /// </summary> public override void Initialize() { OnBeforeInitialized(new ContainerEventArgs(this, ContainerType.Unity)); if (CurrentContext.Application[Name] == null) { lock (_synlock) { if (CurrentContext.Application[Name] == null) { IUnityContainer currentContainer = new UnityContainer(); UnityConfigurationSection section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection; section.Containers[Name].Configure(currentContainer); CurrentContext.Application[Name] = currentContainer; } } } OnAfterInitialized(new ContainerEventArgs(this, ContainerType.Unity)); } /// <summary> /// Resolves this instance. /// </summary> /// <returns></returns> public override T Resolve<T>() { try { Initialize(); IUnityContainer currentContainer = CurrentContext.Application[Name] as IUnityContainer; return currentContainer.Resolve<T>(); } catch (Exception ex) { OnResolveFailed(new ContainerFailedEventArgs(this, ContainerType.Unity, ex)); return default(T); } }
在Initialize()方法中使用了(le)C#的(de)事件(jian),在設置容器(qi)名稱之前與之前各觸發了(le)一個事件(jian),這樣當(dang)有(you)其它(ta)地方對這兩個事件(jian)訂閱時,會在初始化容器(qi)時,被同時觸發。呵呵。夠巧妙吧!


