IOC框架Ninject實踐總結


一、控制反轉和依賴注入

Ninject是一個輕量級的基於.Net平台的依賴注入(IOC)框架。所謂的IOC,即控制反轉(Inversion of Control),它是一個經典的面向對象編程法則,它的作用主要是用來幫助應用程序解耦,並把程序分離成一個個松耦合高內聚的模塊。控制反轉還有一個名字叫依賴注入(Dependency Injection),簡稱DI。

 

二、快速無xml配置注入

1、定義應用程序Module

ServiceModule

2、手動調用服務

InjectManual

 

注:Ninject的綁定對象作用域有多種,本文的demo中有具體的單元測試,具體可以直接查看源碼或者參考官方文檔。。

 

三、配置文件注入

通過Ninject的xml擴展,可以實現傳統的類似於Spring.net、Unity等IOC容器的注入方式。

1、配置文件

<?xml version="1.0" encoding="utf-8" ?>
<module name="ServiceModule">
  <bind name="Txtlog" service="LogService.ILogService,LogService" to="LogService.Impl.TxtLogService,LogService"/>
  <!--<bind name="Dblog" service="LogService.ILogService,LogService" to="LogService.Impl.DbLogService,LogService"/>-->
  <bind name="Sword" service="NinjectApp.Weapon.IWeapon,NinjectApp" to="NinjectApp.Weapon.Sword,NinjectApp"/>
  <bind name="FootSoldier" service="NinjectApp.Warrior.IWarrior,NinjectApp" to="NinjectApp.Warrior.FootSoldier,NinjectApp"/>
</module>

2、利用擴展加載服務

XmlServiceModule

 

3、調用服務

InjectByConfig

 

雖然配置注入看上去更容易擴展應對外部變化,但是項目龐大臃腫之后,配置文件並不好管理。固然有一些可視化的工具,但是仍然容易出現偏差。Ninject最擅長的基本注入功能就是無配置簡單快速注入,達到free yourself from xml的目的,對於一般的中小型應用程序完全可以零配置。

 

四、MVC項目的依賴注入

通過Ninject的MVC擴展可以輕松實現MVC項目的依賴注入。

1、NinjectHttpApplication

在Global.asax.cs文件里重新定義MvcApplication繼承自NinjectHttpApplication,重寫OnApplicationStarted事件和CreateKernel方法:

MvcApplication

 

2、通過構造函數或者屬性或者Module實現注入

(1)、Controller實現注入

a、構造函數注入

Account/Index

b、屬性注入

定義屬性,加上Inject特性即可實現注入。

       [Inject]
        public IUserService CurrentUserService { get; set; }

c、module注入

定義Module:

MvcServiceModule

 

接着調用即可:

MvcServiceModule

 

(2)、自定義Attribute實現注入

ExceptionHandleAttribute

 

和Controller非常相似,示例使用屬性加上Inject特性的方式實現注入,其他注入方式略過。

到這里,你應該已經可以看到,這可以算是web應用程序中非常干凈利落的注入方式,簡單的令人發指。

 

五、組合還是繼承

通過IOC框架實現服務依賴注入本來不難,但是這里或多或少會牽扯到一個問題:注入服務調用是使用組合還是繼承?

舉例來說,最基礎的用戶服務(或者日志服務),一般的web應用程序幾乎每個控制器(或者頁面)都或多或少和用戶有關系。

問題來了,不同的控制器或者頁面要調用用戶服務該怎么做?

下面以MVC項目為例來說明一下通常的注入方法。

如你所知,通常的做法,所謂組合優於繼承(繼承被認為是一種強耦合),我們只要在需要調用服務的控制器中定義一個服務變量或者屬性,通過構造函數注入,類似下面這樣:

controllerconstructor

 

然后在對應的Action中就可以調用用戶服務了。

如果你的Controller很少,這種方式當然可以接受。但是,實際項目中控制器真的比較多的時候,有一些幾乎每個控制器必然用到的公共服務,我們是不是不得不哼哧哼哧寫很多構造函數實現依賴注入呢?

到這里,你一定想到,是啊,都調用一樣的服務,幾乎都類似的代碼,重構吧!

最簡單的方式,利用繼承,集中在一個地方(通常就叫BaseController吧)寫一次,

BaseController

然后,在相應的Controller下this點服務屬性名調用一下,多么優雅干凈簡潔。但是這種方式有一點需要特別需要注意,在Controller的構造函數里調用服務初始化一些數據可能不能讓你那么隨心所欲,因為在構造函數內,服務還沒有初始化。

如上代碼所示,通過Inject特性實現服務注入,通過繼承實現公共服務調用,不管哪種表現形式的應用程序都可以使用,有AOP和繼承的世界看上去是多么美好啊。當然了,具體使用哪種方式好每個人肯定都有自己的看法,實際項目中,我們通常選擇組合和繼承相結合的方式,這樣就可以兼顧兩者的優點實現注入。

最后還有幾個困擾人的問題需要思考:如何划分服務?服務和服務之間是否應該依賴注入?如果僅僅是在表現層實現依賴注入,難道不覺得IOC的作用有點太醬油了嗎?

 

domo下載:NinjectApp

 

參考:http://www.ninject.org/wiki.html

https://github.com/ninject/

 http://ninject.codeplex.com/

http://www.cnblogs.com/cnmaxu/archive/2011/10/25/2224375.html

http://martinfowler.com/articles/injection.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM