精通MVC 5 學習筆記 =========Ninject====>DI容器
雖然我現在還不知道
IKernel ninjectKernel = new StandardKernel();
ninjectKernel.Bind<IValueCalculater>().To<LinqValueCalculator>();
IValueCalculater calcImpl = ninjectKernel.Get<IValueCalculater>();
換下面這一行的好處在哪,但我還是決定深入瞭解一下
IValueCalculater calcImpl = new LinqValueCalculator();
按照書中說的我做了一個平民版:如下:
Models中需要的類和介面:
//產品實體類 public class Product { public int ProductID { get; set; } public string Name { get; set; } public string Description { get; set; } public int Price { get; set; } public string Category { get; set; } } //LINK表示式計算產品總價 public class LinqValueCalculator { public decimal ValueProducts(IEnumerable<Product> product) { return product.Sum(x => x.Price); } } //購物車 public class ShoppingCart { //計算總價的工具類 private LinqValueCalculator cala; //通過建構函式將計算總價的工具類傳入 public ShoppingCart (LinqValueCalculator calcPram) { cala = calcPram; } //商品列表,在執行建構函式的時候可以通過屬性初始化器賦值,也可稍後賦值 public IEnumerable<Product> Products { get; set; } //使用工具類中的方法進行計算總價 public decimal CalculateProductTotal() { return cala.ValueProducts(Products); } }
控制器部分:
public class HomeController : Controller { // GET: Home private Product[] products = { new Product {Name = "香蕉",Category = "水果",Price =2 ,ProductID=0}, new Product {Name = "外套",Category = "衣服",Price =200 ,ProductID=0}, new Product {Name = "平底鍋",Category = "廚具",Price =50 ,ProductID=0}, new Product {Name = "枕頭",Category = "家紡",Price =40 ,ProductID=0}, new Product {Name = "吹風機",Category = "小傢俱",Price =70 ,ProductID=0}, new Product {Name = "香皂",Category = "日用品",Price =8 ,ProductID=0} }; /// <summary> /// 本版本的 Index 方法 和 LinqValueCalculator 與 ShoppingCart 都是強耦合, /// </summary> /// <returns></returns> public ActionResult Index() { LinqValueCalculator calc = new LinqValueCalculator(); ShoppingCart cart = new ShoppingCart(calc) { Products = products }; decimal totalValue = cart.CalculateProductTotal(); return View(totalValue); } }
解析:
可以看到ShoppingCart 和 LinqValueCalculator 是緊耦合的 而且
Home中的Index 對於 LinqValueCalculator 和 ShoppingCart的 耦合是相當高的,所以稱之為平民版本
檢視:
@model decimal
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
Total value is [email protected]
</div>
</body>
</html>
執行結果:
如果後面業務的變動不在適合用 LinqValueCalculator 作為計算總價的方法,需要替換,即便保持替換方法中的總價函式名稱和返回型別以及修飾符,還是和LinqValueCalculator 中一致也需要修改掉 兩處地方 ,一處是ShoppingCart(購物車類)中的
一處是 HomeController 中的:
這感覺改起來是相當酸爽的,
是否進行強化 ? ==============>請新增強化石(DI容器)
戰略兩步走:
一、解開 ShoppingCart 與 LinqValueCalculator 的緊耦合關係:
思路:建立一個介面 呵呵噠 讓 LinqValueCalculator 繼承 , ShoppingCart 中的接收型別使用介面呵呵噠(好比 Object 可以接收 string 一樣)
這個介面呵呵噠 型別例項可以接收 LinqValueCalculator ,由此ShoppingCart 與 LinqValueCalculator 的緊耦合關係解除;現在 Shopping與
介面呵呵噠 緊耦合,這是可以允許的,
情況就好像是 Shopping類是一個30歲的處男,現在的底線只要是雌性動物(只要繼承了呵呵噠 就行),
它就不像17~18歲那會只要美女(LinqValueCalculator ).... 現在是來者不拒
實現程式碼:
/// <summary>
/// 計算總價的介面
/// </summary>
public interface IValueCAlculator
{
decimal ValueProducts(IEnumerable<Product> products);
}
//LINK表示式計算產品總價
public class LinqValueCalculator: IValueCAlculator
{
public decimal ValueProducts(IEnumerable<Product> product)
{
return product.Sum(x => x.Price);
}
}
//購物車
public class ShoppingCart
{
//計算總價的工具類
private IValueCAlculator cala;
//通過建構函式將計算總價的工具類傳入
public ShoppingCart (IValueCAlculator calcPram)
{
cala = calcPram;
}
//商品列表,在執行建構函式的時候可以通過屬性初始化器賦值,也可稍後賦值
public IEnumerable<Product> Products { get; set; }
//使用工具類中的方法進行計算總價
public decimal CalculateProductTotal()
{
return cala.ValueProducts(Products);
}
}
二、解開 Home與 LinqValueCalculator 的緊耦合關係,
現在Home中的情況: 情況似乎更糟了 ,又多了一個強耦合的IValueCAlculator 介面
怎麼讓Home 解開和 IValueCAlculator 與 IValueCAlculator 的實現類 LinqValueCalculator 的耦合呢?
Ninject的工作就是來處理這個問題的