標題「Mvc擴展框架及DI」有點繞口,我也想不出好的命名,由於這個內容很雜,涉及多個模塊,但在平常開發又密不可分html
首先說Mvc擴展框架,該Mvc擴展就是把之前的那個Mvc分區擴展框架遷移過來,並優化整合了一下數組
1、Mvc擴展框架主要功能:緩存
一、Mvc的依賴注入(DI)功能(類MvcDependency)安全
依賴IContainerFactory接口,再也不依賴具體容器app
二、Mvc全局過濾器(GlobalFilterProvider)框架
配置在Mvc的依賴注入容器中就能自動被Mvc調用。其實邏輯很簡單,就是繼承IFilterProvider接口,對外暴露Filters屬性,須要增長過濾器就配置到Filters屬性中ide
三、分模塊(Area分區)開發支持工具
Area基類及相關支持類(AreaRoute、AreaListService)性能
四、分區過濾器(AreaGlobalFilterProvider)學習
五、分區註冊的HttpModule(AreaMergeModule)
使用該HttpModule初始化分區及分區的依賴注入容器配置
2、依賴注入(DI)也挺複雜的
一、Mvc的依賴注入(DI)支持
Mvc使用IDependencyResolver接口定義依賴注入,實現該接口並覆蓋Mvc默認的DI配置,主要是把Mvc的依賴注入適配到容器來支持,以便使用容器來作
二、容器的依賴注入(DI)
成熟容器支持依賴注入功能,爲用戶構造對象,並按當前對象(類)的依賴注入配置遞歸進行依賴注入操做
三、框架的依賴注入(DI)擴展(Fang.DI)
其1、本框架不依賴任一成熟容器,因此爲了便於更好的使用DI技術,因此擴展了DI支持,以便使用任意容器功能均可以使用DI
其2、每種成熟容器的DI配置(標註)的方式不一致,致使使用特定容器的DI寫的代碼給使用其餘容器技術的團隊複用性很差
其3、本框架支持「快速檢索黑科技」(參考核心容器那篇),使用該依賴注入(DI)擴展可使用「快速檢索黑科技「語法定義依賴注入標記
本篇內容涉及」Mvc擴展框架「子模塊,」依賴注入(DI)擴展「子模塊、主框架的核心容器及外部成熟容器(本篇繼續使用Unity容器作外部成熟容器示例)
介紹的差很少了,先上例子
1、Mvc的依賴注入(DI)
一、使用Unity容器作DI
1.1 配置初始化
首先注入Unity容器,初始化Mvc依賴配置(替代Mvc默認的DependencyResolver)
1.2 建一個測試頁面,使用Unity配置一個依賴注入服務
Ok,依賴注入成功
1.3 看一下Unity容器配置
二、使用Fluent代碼作依賴注入
木有問題,效果出來。使用容器技術不必定非要用配置文件,Fluent方式也是配置容器的選項之一。固然配置文件搭配Fluent也是木有問題。
以上例子雖然簡單,但用到了不少技術,有Mvc擴展框架、Unity容器及依賴注入(DI)擴展。
2、全局過濾器
一、過濾器代碼很簡單
以上只是ActionFilter的例子,Mvc支持的AuthorizationFilter\ExceptionFilter\ActionFilter\ResultFilter均可以這樣配置,是否是很爽啊
二、看一下容器配置信息
有人說,你能用Fluent代碼再做一次過濾器的例子嗎?固然能夠,只要建立一個IFilterProvider對象,注入到容器裏面就能夠了。不必再作這個重複的工做。
我是很是推薦使用配置文件的方式,項目和調用的服務具體實現類才能完全的隔離,才能更好的體現IOC容器的做用
3、分模塊(area分區)
一、分區路由配置
二、兩個分區配置
三、執行效果
以上兩個分區運行結果,且兩個分區調用的服務稍有不一樣,致使結果稍不一樣
分區的講解不展開了,參看原來的文章」分區擴展框架「,只是分區過濾器稍有不一樣,後面再講解分區過濾器
4、分區過濾器
一、仍是使用全局過濾的代碼,直接看結果
以上實際上是分區過濾器和全局過濾器整合測試,兩個分區共用一個全局過濾器GlobalTest,每一個分區還有本身的分區過濾,效果不錯吧
二、看一下過濾器配置(配置和全局過濾器是不一樣的)
看以上配置,分區過濾器和全局過濾器配置幾乎一致(實際上也是繼承關係),並且從分區中拆分出來,效果和原來(參看原來文章」分區擴展框架「)同樣,結構是不清晰多了,並且也減輕了area初始化的負擔,算是優化吧。
三、AreaMergeModule(分區註冊的HttpModule)配置
配置方法仍是那麼簡單,這方面的內容仍是參看前篇文章
5、框架的依賴注入(DI)擴展(Fang.DI)
一、配置方式
和Unity的屬性依賴注入類似度很高吧,只是命名空間不同,可是做用大不少,還能夠對不支持DI的容器進行DI(依賴注入)
二、執行效果
效果和Unity容器配置的同樣。使用DI擴展對不一樣容器就能夠統一依賴注入語法了。可是美中不足的是,我只在依賴注入擴展模塊(Fang.DI)中實現了屬性依賴注入。
這種擴展DI並不會覆蓋原容器(好比Unity)的DI,只是補充,也會檢測DI的屬性是否已經初始化(!=null),也就是說擴展的DI是補充,原容器DI成功就再也不DI,也能夠同時使用(若是你不嫌亂的話)
我我的認爲有屬性依賴注入就夠用了。固然不少人都有反駁的理由,最爲關鍵的應該是安全性。若是咱們把服務的初始化都交給容器,不要去修改服務對象,也就沒有安全一說;若是你非要修改,就算是private的,類內部也能夠修改,外部使用反射也能修改,沒有絕對的安全性。
三、使用「快速檢索黑科技「語法定義依賴注入標記
上面標註中重點要看到有個點(.),本例就是把全局服務容器中的默認時間格式化服務DI到當前Controller的屬性上;也就是說能夠把任意容器中的任意服務都DI過來,絕對的黑科技!!!
6、各功能模塊都是如何協同工做的
一、Mvc擴展框架、Unity容器及依賴注入(DI)擴展模塊相互獨立,相互沒有依賴關係
上圖能夠清晰看到,他們相互獨立,可是他們都依賴着面向接口主框架(Fang.Framework),那主框架就很是重要,各自和主框架的關係就很是重要
(這就是我設計這個框架的初衷,之後增長再多的功能,或者引入再多的第三方組件,都只依賴主框架,都是對做爲主框架的服務(插件)或者Mvc等Ms框架的插件來調用運行)
二、以上例子中各模塊式如何工做
先看項目配置
以上先註冊Unity容器,再註冊依賴注入擴展(Fang.DI),分區及其路由規則使用HttpModule注入
咱們還看到一個有意思的東西,初始化DI竟然和初始化Unity容器那麼的類似,其實DI擴展就是容器封裝,說白了就是容器擴展,也就是說我是經過擴展容器來實現DI的
三、那咱們看看依賴注入擴展(Fang.DI)怎麼工做的
3.1 依賴注入擴展(Fang.DI)項目截圖
A:DependencyAttribute就是依賴注入標註(Attribute),靠他標註哪一個屬性須要注入
B:Container和ContainerFactory是容器封裝,封裝後的容器對象就有了擴展出來的DI功能,因此咱們調用的原始容器即便沒有依賴注入功能通過這麼一封裝就有依賴注入功能了
C:PropertyChecker類就是負責找到那些屬性須要依賴注入,PropertyChecker實例對象封裝了一個屬性的依賴注入過程(功能)
D:CheckContainer定義了一個使用容器處理依賴注入的接口(ICheckContainer)及多個Checkers屬性包含多個ICheckContainer對象,並本身實現ICheckContainer接口
(其實就是容器處理依賴注入的組合模式,其中前面的PropertyChecker就是實現的ICheckContainer接口,通常來講CheckContainer對象包含一個PropertyChecker的數組)
注:這塊剛開發完,CheckContainer這個命名有點問題,之後再改,若是有建議好的命名能夠回覆我一下,謝謝
3.2 再來看一下CheckContainer的主要邏輯(仍是比較簡單的)
解讀一下:
A:字典(ConcurrentDictionary)按類型緩存對象
B:MonitorWrapper是我寫的一個對象鎖的封裝,避免死鎖和控制鎖定的最長時間(默認50毫秒)及返回是否鎖定成功;
(既然是緩存,那鎖只是幫咱們提升緩存利用率的工具,因此不論是否鎖定成功,都繼續執行)
C:若是沒有緩存,咱們按類型獲取可寫並標註(DependencyAttribute)的屬性,按屬性構造注入功能(ICheckContainer)對象
D:這裏的注入比較簡單,我直接使用的反射了;
(打算之後使用Emit,可是個人Emit功底太差,Emit個功能要半天,之後在好好學習Emit技巧或者花時間好好調試,爲了性能不能有半點馬虎)
本篇內容就講完了。本篇內容和原來的那篇」分區擴展框架「有不少相同的地方,但本質的東西區別很大。原來的分區框架是強依賴Unity容器的,本框架是使用配置到主框架的容器工廠。
不少配置也都有更多的自定義化,並且本框架也照顧到不使用分區的開發使用者的利益(全局過濾和MvcDependency(DI))。
還有就是依賴注入擴展模塊(Fang.DI)和Mvc擴展框架無縫結合,真是如虎添翼。固然,Fang.DI在非Mvc中的也是同樣有效,這裏就不舉例說明了。