標籤:ninject ioc 依賴注入
ASP.NET MVC學前篇之Ninject的初步瞭解
1.介紹
廢話幾句,Ninject是一種輕量級的、基礎.NET的一個開源IoC架構,在對於MVC架構的學習中會用到IoC架構的,因為這種IoC開源架構有很多,本篇的主題只有一個,就是讓閱讀過本篇幅的朋友逗知道IoC架構在項目中的作用,以及它的重要性。 這樣做的目的是以便在以後的學習工作中選擇自己中意的一個IoC架構來學習、使用,或者是自己去實現一個。好了,不廢話了。
2.環境準備
1.建立個4.0Framework的一個控制台應用程式項目,名稱為IoCDemo
2.在http://www.ninject.org/download網頁中,下載Version 2.2版本的Ninject程式集(之前版本的不支援4.0庫),下載完成解壓後會看到1裡的幾個檔案,在這裡你只需要關心名稱為Ninject的檔案,其它的忽略掉。
圖1
650) this.width=650;" src="http://images.cnitblog.com/i/627988/201406/022224256451966.png" />
3.在項目中建立個Lib檔案夾,並把Ninject.dll、Ninject.pdb和Ninject.xml三個檔案拷貝到檔案目錄下,並且添加引用到項目中。2:
圖2
650) this.width=650;" src="http://images.cnitblog.com/i/627988/201406/022225202706311.png" />
環境準備工作做好了,可以安心的來看樣本了。捎帶一句Ninject.xml檔案是組件檔的注釋,不過都是英文的,對於姿勢水平不高的屌絲來說這並不算是福利,當然也包括本人。(ps:Google翻譯什麼的很好用)
3.初步認識、瞭解
從上一篇的文章中,可以瞭解到一個基礎的IoC,這是站在容器物件的角度去考慮的,具體實現對象確實是可以動態注入到容器物件中的。我們再看一下新的樣本,並從中找到上一篇不足的地方,換個角度去看問題。
我們先定義了一個商品類,內容只包含了商品的編號、名稱和價格三個屬性
代碼3-1
1 /// <summary>2 /// 貨品3 /// </summary>4 public class Commodity5 {6 public string CommodityID { get; set; }7 public string Name { get; set; }8 public float Price { get; set; }9 }
商品類型定義好了之後,我們再定義個貨品的計價規範和它的一個基礎實現
代碼3-2
1 /// <summary> 2 /// 貨品計價規範 3 /// </summary> 4 public interface IValuation 5 { 6 float CommodityValuation(params Commodity[] commodities); 7 } 8 9 /// <summary>10 /// 貨品計價規範實現一:商品價格合計11 /// </summary>12 public class CommoditySumValuation : IValuation13 {14 public float CommodityValuation(params Commodity[] commodities)15 {16 return commodities.Sum(commodity => commodity.Price);17 }18 }
這樣看來架勢和上一篇的相同,前段的確實是差不多的,不要著急慢慢來看。再定義個容器物件,並且通過構造注入的方式來實現解耦,讓容器物件和具體實現徹底的分離了。
代碼3-3
1 /// <summary> 2 /// 購物車-容器物件 3 /// </summary> 4 public class ShoppingCart 5 { 6 private IValuation _Valuation; 7 public ShoppingCart(IValuation valuation) 8 { 9 _Valuation = valuation;10 }11 12 public float CommodityTotalPrice()13 {14 Commodity[] commodities =15 {16 new Commodity(){ CommodityID="A1", Price=14},17 new Commodity(){ CommodityID="A2", Price=76.5f},18 new Commodity(){ CommodityID="B2", Price=34.4f},19 new Commodity(){ CommodityID="C4", Price=23.1f}20 };21 22 return _Valuation.CommodityValuation(commodities);23 }24 }
對於上面那句話的定義,站在不同角度定義結果是不同的,如果站在容器物件的角度來看,確實是實現瞭解耦,3
圖3
650) this.width=650;" style="width:730px;height:231px;" src="http://images.cnitblog.com/i/627988/201406/022229150363623.png" width="711" height="181" />
可以明確的看到ShoppingCart類型(容器)和CommoditySumValuation類型(具體實現)沒有任何的關係,從而以達到解耦的目的,但是問題要結合到實際從用戶端調用容器物件來看:
代碼3-4
1 namespace IoCDemo 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 ShoppingCart shoppingCart = new ShoppingCart(new CommoditySumValuation()); 8 9 }10 }11 }
代碼看到這裡,想必大家都會頭疼了,這整的叫什麼事,饒了一圈還是耦合了。4
圖4
650) this.width=650;" style="width:741px;height:266px;" src="http://images.cnitblog.com/i/627988/201406/022232463178508.png" width="825" height="229" />
這種情況下IoC架構就可以派上用場了,本篇介紹的是Ninject,那當然是用Ninject了,根據前面的環境配置,
代碼3-5
1 using Ninject; 2 3 namespace IoCDemo 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 #region IoC架構功能10 IKernel kernel = new StandardKernel();11 kernel.Bind<IValuation>().To<CommoditySumValuation>();12 IValuation valuation = kernel.Get<IValuation>();13 #endregion14 15 ShoppingCart shoppingCart = new ShoppingCart(valuation);16 Console.WriteLine(shoppingCart.CommodityTotalPrice().ToString());17 Console.ReadLine();18 }19 }20 }
這裡是通過Ninject中的IKernel類型的Bind泛型方法來綁定IValuation類型,用To泛型方法中的類型表示是Bind方法中類型的實現,這樣在kernel.Get<IValuation>()的時候是返回的CommoditySumValuation類型。這裡對Ninject的使用並不多做介紹,而是側重的解釋IoC的重要性及其作用。
這個時候的依賴結構如5
圖5
650) this.width=650;" style="width:738px;height:261px;" src="http://images.cnitblog.com/i/627988/201406/022234396928238.png" width="623" height="187" />
這樣可能看不出IoC的效果,我們再新增一些需求,並且更改CommoditySumValuation實作類別,
代碼3-6
1 /// <summary> 2 /// 計價折扣演算法規範 3 /// </summary> 4 public interface IValuationDisCount 5 { 6 float ValuationDisCount(float listPrice); 7 } 8 9 /// <summary>10 /// 計價折扣演算法規範實現一:九折 走起11 /// </summary>12 public class DisCount : IValuationDisCount13 {14 15 public float ValuationDisCount(float listPrice)16 {17 return listPrice - (listPrice * 10 / 100);18 }19 }
添加了一個新需求規範和一個新的實作類別,這樣可以給商品總和來打折了,還需在CommoditySumValuation實作類別中實現構造注入,修改代碼如下:
代碼3-7
1 /// <summary> 2 /// 貨品計價規範實現一:商品價格合計 3 /// </summary> 4 public class CommoditySumValuation : IValuation 5 { 6 private IValuationDisCount valuationDisCount; 7 8 public CommoditySumValuation(IValuationDisCount valuationdiscount) 9 {10 this.valuationDisCount = valuationdiscount;11 }12 13 public float CommodityValuation(params Commodity[] commodities)14 {15 return valuationDisCount.ValuationDisCount(commodities.Sum(commodity => commodity.Price));16 }17 }
這個時候如果沒有IoC架構的存在,看下用戶端是怎麼來調用的:
代碼3-8
1 using Ninject; 2 3 namespace IoCDemo 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 ShoppingCart shoppingCart =10 new ShoppingCart(new CommoditySumValuation(new DisCount()));11 12 Console.WriteLine(shoppingCart.CommodityTotalPrice().ToString());13 Console.ReadLine();14 }15 }16 }
運行一下同樣也能得到結果,但是不管怎麼的去抽象,在用戶端調用都需要直接依賴於實作類別,而不是高層次的抽象,
圖7
650) this.width=650;" style="width:738px;height:181px;" src="http://images.cnitblog.com/i/627988/201406/022238017551973.png" width="697" height="160" />
可以看出來這是多麼的恐怖。重新的修改下Main函數裡的代碼把IoC架構給使用起來。
代碼3-9
1 using Ninject; 2 3 namespace IoCDemo 4 { 5 class Program 6 { 7 static void Main(string[] args) 8 { 9 #region IoC架構功能10 IKernel kernel = new StandardKernel();11 kernel.Bind<IValuation>().To<CommoditySumValuation>();12 kernel.Bind<IValuationDisCount>().To<DisCount>();13 IValuation valuation = kernel.Get<IValuation>();14 #endregion15 16 ShoppingCart shoppingCart = new ShoppingCart(valuation);17 18 Console.WriteLine(shoppingCart.CommodityTotalPrice().ToString());19 Console.ReadLine();20 }21 }22 }
結果8:
圖8
650) this.width=650;" src="http://images.cnitblog.com/i/627988/201406/022239150831306.png" />
再來看一下依賴結構,
圖9
650) this.width=650;" style="width:745px;height:213px;" src="http://images.cnitblog.com/i/627988/201406/022240407701827.png" width="756" height="213" />
Ninject架構會檢查要返回的類型所依賴的所有類型,並且也會動態注入到類型當中。
從圖7和圖9的對比中可以看出,只有通過增加IoC架構來進行用戶端和具體實現的解耦,沒有這個中介層的加入還真的不好來實現消除耦合,並且IoC架構還可以進行動態配置。
本篇到這裡結束了,對Ninject感興趣的朋友請自行學習吧。
本文出自 “金源” 部落格,請務必保留此出處http://jinyuan.blog.51cto.com/8854733/1423570