新聞中心
一、前言

臨河網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)公司!從網(wǎng)頁設計、網(wǎng)站建設、微信開發(fā)、APP開發(fā)、響應式網(wǎng)站設計等網(wǎng)站項目制作,到程序開發(fā),運營維護。成都創(chuàng)新互聯(lián)公司自2013年起到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設就選成都創(chuàng)新互聯(lián)公司。
在《上篇》中,基本的項目結構已經(jīng)搭建起來了,但是有個問題,層與層之間雖然使用了接口進行隔離,但實例化接口的時候,還引入了接口實現(xiàn)類的依賴。如下圖:
面向接口編程,Controller應該只依賴于站點業(yè)務層的接口,而不能依賴于具體的實現(xiàn),否則,就違背了在層之間設置接口的初衷了。
另外,如果上層只依賴于下層的接口,在做單元測試的時候,就可以用Moq,F(xiàn)akes等Mock工具來按實際需求來模擬接口的實現(xiàn),就可以靈活的控制接口的返回值來對各種情況進行測試,如果依賴于具體的實現(xiàn),項目的可測試性將大大減小,不利于進行自動化的單元測試。
要不依賴于具體的實現(xiàn),就不能使用通常的 T t = new T() 的方式來獲得一個類的實例了,需要通過IOC容器來對對象生命周期,依賴關系等進行統(tǒng)一的管理。
二、MEF的優(yōu)勢
.net中可用的IOC容器非常多,如 CastleWindsor,Unity,Autofac,ObjectBuilder,StructureMap,Spring.Net等,這些第三方工具各不相同,但功能大體都相同,大都需要事先對接口與實現(xiàn)進行配對(通過代碼或配置文件),然后由系統(tǒng)自動或手動來通過接口來獲得相應實現(xiàn)類的實例,對象實例化的工作由IOC容器自動完成。
MEF相對于上面的這些IOC容器有什么優(yōu)勢呢?下面是我推薦的理由:
- .net4.0 自帶:MEF的功能在 System.ComponentModel.Composition.dll 程序集中,直接引用即可使用,不用安裝第三方組件
- 0 配置:MEF是不需要使用配置文件或代碼對接口與實現(xiàn)進行一一配對的,只需要簡單的使用幾個Attribute特性,就能自動完成源與目標的配對工作
- 自動化:系統(tǒng)初始化時自動遍歷程序目錄或指定文件夾下的dll,根據(jù)程序集中接口與類的特定Attribute特性進行自動配對。
三、MEF在桌面程序中的使用
在桌面程序中,需要完成兩個部分的目錄匹配,一個是dll中的匹配,另一個為exe程序集中的匹配,分別使用到 DirectoryCatalog與AssemblyCatalog兩個目錄類。而兩個目錄類需加入到 AggregateCatalog 目錄類中,才能參與組合容器CompositionContainer的初始化。
在服務提供方的實現(xiàn)類中,使用 ExportAttribute 標記要與之匹配的接口,如下圖所示。在服務調用方,使用 ImportAttribute 來給接口注入實現(xiàn)類的實例,如上圖所示。
由于調用方法為靜態(tài)的方法,Program類的實例仍需手動從組件容器中獲得,然后嘗試登錄:
輸出結果,接口AccountContract并沒有賦值,但能輸出其實現(xiàn)類的信息,同時登錄也能成功調用:
四、MEF在MVC中的使用
在MVC的項目中,IOC組件是通過 DependencyResolver類中的 SetResolver(IDependencyResolver resolver) 方法來向MVC提供注冊點的,所以我們只需要實現(xiàn)一個 IDependencyResolver 接口的MEF實現(xiàn)類,即可完成MEF在MVC中的注冊工作。
另外考慮到Web應用程序的無狀態(tài)性,即每次訪問都是獨立進行的,所以IOC組件產(chǎn)生的對象實例也必須唯一,否則不同用戶的操作就可能串線,產(chǎn)生相互干擾。在這里,我們使用HttpContext.Current.Items集合來保存 組合容器CompositionContainer的實例,以使每個用戶的數(shù)據(jù)保持獨立,并且同一用戶的同一個Http請求中使用同一對象實例。另外考慮到可能會有某種情況下需要手動獲取組合容器中的實例,把組合容器緩存到了當前上下文中的Application中。
MefDependencySolver實現(xiàn)代碼如下:
- ///
- /// MEF依賴關系解析類
- ///
- public class MefDependencySolver : IDependencyResolver
- {
- private readonly ComposablePartCatalog _catalog;
- private const string HttpContextKey = "MefContainerKey";
- public MefDependencySolver(ComposablePartCatalog catalog)
- {
- _catalog = catalog;
- }
- public CompositionContainer Container
- {
- get
- {
- if (!HttpContext.Current.Items.Contains(HttpContextKey))
- {
- HttpContext.Current.Items.Add(HttpContextKey, new CompositionContainer(_catalog));
- }
- CompositionContainer container = (CompositionContainer)HttpContext.Current.Items[HttpContextKey];
- HttpContext.Current.Application["Container"] = container;
- return container;
- }
- }
- #region IDependencyResolver Members
- public object GetService(Type serviceType)
- {
- string contractName = AttributedModelServices.GetContractName(serviceType);
- return Container.GetExportedValueOrDefault
- }
- public IEnumerable
- {
- return Container.GetExportedValues
- }
- #endregion
- }
#p#
在Global.asax.cs的Application_Start方法中初始化MEF容器,由于Web應用程序中只需要在DLL中查找匹配,所以只使用DirectoryCatalog即可。
在AccountController類中加入MEF的Attribute標簽,并刪除原來構造函數(shù)中的AccountContract屬性的賦值代碼
在加入了IOC組件之后,我們的架構就變成了面向接口編程的架構了,上層代碼僅依賴于下層的接口,而不依賴于下層的具體實現(xiàn),為了防止站點業(yè)務層的實現(xiàn)代碼中出現(xiàn)如下所示的代碼:
- IAccountSiteContract accountContract = new AccountSiteService();
上一篇文章中也提到過,需要把站點業(yè)務層中的實現(xiàn)類的可訪問性由 public 修改為 Internal,以實現(xiàn)上層代碼對下層代碼的真正隔離。
其他代碼不變,運行網(wǎng)站,同樣能正常調用登錄功能
***,給個溫馨提示:
MEF的導出導入是整體關聯(lián)的,只要樹中某一個部件匹配失敗,整個樹將無法實例化,也就是會出現(xiàn)Import的屬性值為null的情況,這種情況下,可以使用MEF開發(fā)團隊提供的調試工具MEFX來進行問題的快速定位。具體使用方法參考如下:
- 結構分析工具 (Mefx)
- 調試 MEF
五、源碼獲取
GMFrameworkForBlog2.zip
為了讓大家能***時間獲取到本架構的***代碼,也為了方便我對代碼的管理,本系列的源碼已加入微軟的開源項目網(wǎng)站 http://www.codeplex.com,地址為:
https://gmframework.codeplex.com/
可以通過下列途徑獲取到***代碼:
- 如果你是本項目的參與者,可以通過VS自帶的團隊TFS直接連接到 https://tfs.codeplex.com:443/tfs/TFS17 獲取***代碼
- 如果你安裝有SVN客戶端(親測TortoiseSVN 1.6.7可用),可以連接到 https://gmframework.svn.codeplex.com/svn 獲取***代碼
- 如果以上條件都不滿足,你可以進入頁面 https://gmframework.codeplex.com/SourceControl/latest 查看***代碼,也可以點擊頁面上的 Download 鏈接進行壓縮包的下載,你還可以點擊頁面上的 History 鏈接獲取到歷史版本的源代碼
- 如果你想和大家一起學習MVC,學習EF,歡迎加入Q群:5008599(群發(fā)言僅限技術討論,拒絕閑聊,拒絕醬油,拒絕廣告)
- 如果你想與我共同來完成這個開源項目,可以隨時聯(lián)系我。
分享標題:MVC實用架構設計:使用MEF應用IOC(依賴倒置)
URL地址:http://fisionsoft.com.cn/article/dpdopic.html


咨詢
建站咨詢
