1. 程式人生 > >精通MVC 5 學習筆記 =========Ninject====>DI容器

精通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的工作就是來處理這個問題的