今天的主題是ASP.NET MVC中的依賴注入這些事,依賴注入開始是叫作IoC也就是控制反轉了,後來被rename了。廢話到此結束。那麼咱們爲何要在ASP.NET MVC中時候DI呢?這DI有什麼神奇的地方讓ASP.NET MVC如此的愛它。爲了解決這個問題呢,咱們先來看看,爲何要依賴注入。其實在MVC中一個重要的特徵就是關注分離,咱們但願咱們的應用程序儘量的相互獨立,儘量的減小彼此的依賴,一個理想的應用程序應當是一個組件能夠不知道或者說不關心其它組件的存在,可是能夠經過一個公開的接口能夠調用其它的組件。這也就是所謂的鬆耦合。css
這裏能夠舉一個很簡單的例子說明。好比我定義了一個接口IprintStr,在這個接口裏就是一個方法,string printName(string name);以後呢,咱們再定義一個類來繼承這個接口:printStr:IprintStr.類的具體實現我這裏再也不累贅。如今呢咱們要實現這個類提供的服務操做,咱們再定義一個類。叫作execute.cs咱們在這個execute.cs類中能夠這麼寫:IprintStr str = new printStr(); string myName = str.printName(「David Zhang」);以後輸出。到此這個例子就結束了。咱們接着來思考下。在咱們這個簡單例子中execute類是經過IprintStr接口而不是直接經過printStr類實現,若是之後我這個execute要發生大的變化,要實現其餘的功能,那麼我能夠這樣寫 IprintStr str = new xxxXX();也就是換掉new後面的對象。其餘的代碼保持不變。在這裏呢咱們實現了必定的鬆耦合。在這個例子中呢,咱們的printStr類既依賴於IprintStr也依賴於execute類。在這裏呢就會出現這樣一個問題,加入有一天咱們這個printStr類出現了莫名其妙的問題,那麼是否是咱們的execute這個類也要進行維護。這是很麻煩的一件事。最好的辦法就是,這裏的IprintStr,printStr和execute三個不一樣的組件相互的分開,彼此之間沒有半毛錢的關係。而咱們的依賴注入就是爲了解決這樣的問題!html
什麼是依賴注入java
其實在應用程序中呢,在一個執行類中,不經過建立服務類的對象的實例,咱們就能夠得到某個公開接口的對象的引用。也能夠這麼說依賴注入是一個過程,因爲執行類只依賴於服務類的一個接口,而不依賴於具體的服務類,因此呢,在客戶類中只定義一個注入點,在程序運行的時候,執行類不直接實例化服務類的具體兌現,而是執行類運行上下文的專門的組件來負責實例化服務類,以後呢,將其注入到執行類中。這樣,執行類得以正常的運行。編程
依賴注入的類別mvc
這裏我就說下setter注入和構造注入吧。其它的不怎麼用框架
首先是setter注入:也就是在執行類中,設置一個服務類接口類型的數據成員,而且設置一個set方法做爲注入點,這個set方法接受一個具體服務類實例做爲參數,而且把它賦給服務類接口類型的數據成員 ide
public class execute
{
IprintStr printStr;
public void set_execute(IprintStr printStr)
{
this.printStr = printStr;
}
public string printNameFun(string name)
{
string testExam= printStr.printName(name);
return testExam;
}
}
還有一個就是構造注入(Constructor Injection)this
public class execute
{
IprintStr printStr;
public execute(IprintStr printStr)
{
this.printStr = printStr;
}
public string printNameFun(string name)
{
string testExam= printStr.printName(name);
return testExam;
}
}
構造注入呢,也就是setter注入方法變成了構造方法。這裏要注意的是,構造注入只能注入一次,在程序運行期間,沒有辦法改變執行類中的服務類對象實例。spa
到了這裏,咱們不得不談到Ioc Container..net
用於實現依賴注入的框架或者是組件就是Ioc Container.好比java平臺十分紅熟的重量級Ioc Container Sping和一直到.net平臺的Spring.net.以及一些輕量級的Ioc Container好比本文要說的unity和ninject。
咱們先說說ninject吧!
如何獲得。咱們能夠經過vs中的NuGet包管理器進行下在,它自動能夠添加到相關的namespace到你的項目中,咱們要作的就是在要的時候,using下!我這裏已經using了,下面就很簡單了。
1: static void Main(string[] args)
2: {
3: IKernel ninjectKernel = new StandardKernel();
4: //綁定接口道實現該接口的類
5: ninjectKernel.Bind<IprintStr>().To<recName>();
6: //得到實現接口的對象實例
7: IprintStr iprintStr = ninjectKernel.Get<IprintStr>();
8: //建立recName實例而且實現注入依賴
9: string str = iprintStr.printName("This is David Zhang Home Page.");
10: Console.WriteLine(str);
11: Console.ReadKey();
12: }
這裏咱們仍是應用上面咱們談的例子。關鍵部分上面已經註釋了!我在這裏就再也不累贅了,這裏的recName就是開始咱們說的實現IprintStr的printStr,由於有些變更沒有改過來!。關於具體的ninject的API,你能夠Google。我這裏再也不多篇幅的說明。咱們就用在ASP.NET MVC 中使用的unity Container吧,由於最近的項目裏用到了它,同時但願這邊博文給正在作項目的朋友們以參考。只當是拋磚引玉吧。
Ioc能夠對ASP.NET MVC 的Controller進行注入,要想實現Controller的依賴注入,就須要讓IoC容器接管Controller的建立,而ASP.NET MVC 3中提供的IDependencyResolver接口就爲實現這個提供了可能。因此,咱們首先建立一個實現IDependencyResolver接口的UnityDependencyResolver類,
1: public class UnityDependencyResolver : IDependencyResolver
2: {
3: IUnityContainer container;
4: public UnityDependencyResolver(IUnityContainer container)
5: {
6: this.container = container;
7: }
8:
9: public object GetService(Type serviceType)
10: {
11: try
12: {
13: return container.Resolve(serviceType);
14: }
15: catch
16: {
17: return null;
18: }
19: }
20:
21: public IEnumerable<object> GetServices(Type serviceType)
22: {
23: try
24: {
25: return container.ResolveAll(serviceType);
26: }
27: catch
28: {
29: return new List<object>();
30: }
31: }
32: }
這裏對null的說明:在IDependencyResolver.GetService(Type serviceType)的實現中,判斷一下serviceType是否被註冊,若是沒有被註冊,就返回null。ASP.NET MVC獲得null返回值,會本身解析這個接口。好了,咱們如今實現了這個IDependencyResolver。還有一個很重要的一點就是你要告訴MVC,在這裏咱們建立了unityDependencyResolver,他要被解析,咱們能夠在Global.asax的Application_Start()中添加:
IUnityContainer container = new UnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
固然了,說到這裏,還有一點咱們沒有涉及,你們能夠看到上面我用ninject寫的一個小例子,它有一個ninjectkernel.Bind<Ixxx>().To<xxx>().這個通俗的時候也就是註冊,世間萬物都是類似的,咱們在unity中也有相似的,如:
container.RegisterType<Ixxx, xxx>();那麼咱們如何進行註冊呢,有連個辦法:第一就是在你須要的Controller中進行相關的註冊,或者將全部的註冊相關的代碼統一到一個類文件中, 好比類:DependencyRegisterType,將全部的註冊寫到一個靜態的方法中,以後再Application_Start()中進行運行。最後一點就是在相關的Controller中要這樣寫:
[Dependency]
public IxxxL _xxxL { get; set; }
以後進行相關的調用。編程效率那是大大的增長啊!!省去了很多new.
okay,That’s all.時間不早了,Good Night
關於本博文聲明:
本博文屬於原創博文,容許轉載。但要保留原連接!因爲時間倉促,沒有細心校對,博文可能有些地方不完善或者說是有錯誤。歡迎雅正:)
博文部分參考:
http://www.cnblogs.com/dudu/archive/2011/06/09/unity_mvc_idependencyresolver.html
http://www.cnblogs.com/techborther/archive/2012/01/06/2313498.html