項目結構圖:
App_start文件夾中的文件是VS自己創建的,其中NinjectWebCommon類在創建之初并不存在。后面會再次提到!
添加一個Home控制器。代碼如下:


using EssentialTools.Models; using Ninject; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc;namespace EssentialTools.Controllers {public class HomeController : Controller{private IValueCalculator calc;Product[] products ={new Product{Name="Kayak",Category="Watersports",Price=275M},new Product{Name="LifeJacket",Category="Watersports",Price=48.95M},new Product{Name="Soccer Ball",Category="Soccer",Price=19.50M},new Product{Name="Corner Flag",Category="Soccer",Price=34.95M}};public HomeController(IValueCalculator calcParam){calc = calcParam;}public ActionResult Index(){ //IKernel ninjectKernel = new StandardKernel();//ninjectKernel.Bind<IValueCalculator>().To<LinqValueCalculator>();//LinqValueCalculator calc = new LinqValueCalculator();//return View(calc.ValueProducts(products));ShoppingCart cart = new ShoppingCart(calc) { Products = products };decimal totalValue = cart.CalculateProductTotal();return View(totalValue);}} }
為控制器中的Index方法添加視圖。代碼如下:


@model decimal @{ViewBag.Title = "Index";Layout = null; }<div> Total value is $@Model</div>
創建Infrastructure文件夾,在該文件夾下創建Ninject的依賴解析器。代碼如下:


using EssentialTools.Models; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using Ninject;namespace EssentialTools.Infrastructure {public class NinjectDependencyResolver : IDependencyResolver{private IKernel kernel;public NinjectDependencyResolver(IKernel knernelParam){kernel = knernelParam;AddBindings();}public object GetService(Type serviceType){return kernel.TryGet(serviceType);}public IEnumerable<object> GetServices(Type serviceType){return kernel.GetAll(serviceType);}private void AddBindings(){kernel.Bind<IValueCalculator>().To<LinqValueCalculator>();}} }
在Models文件夾中攢關鍵1個接口,3個類。代碼如下:


using System; using System.Collections.Generic; using System.Linq; using System.Web;namespace EssentialTools.Models {public interface IValueCalculator{decimal ValueProducts(IEnumerable<Product> products);} }


using System; using System.Collections.Generic; using System.Linq; using System.Web;namespace EssentialTools.Models {public class LinqValueCalculator : IValueCalculator{public decimal ValueProducts(IEnumerable<Product> products){return products.Sum(p => p.Price);}} }


using System; using System.Collections.Generic; using System.Linq; using System.Web;namespace EssentialTools.Models {public class Product{public int ProductID { get; set; }public string Name { get; set; }public string Description { get; set; }public decimal Price { get; set; }public string Category { get; set; }} }


using System; using System.Collections.Generic; using System.Linq; using System.Web;namespace EssentialTools.Models {public class ShoppingCart{IValueCalculator calc;public ShoppingCart(IValueCalculator calcParam){calc = calcParam;}public IEnumerable<Product> Products { get; set; }public decimal CalculateProductTotal(){return calc.ValueProducts(Products);}} }
使用nuget安裝Ninject
工具→庫程序包管理器→程序包管理器控制臺
安裝ninject內核包:
install-package Ninject -version 3.0.1.10
安裝ninject內核包的拓展包:
install-package Ninject.Web.Common -version 3.0.0.7
對MVC3的引用(在mvc5中仍能用到)
install-package ninject.mvc3 -version 3.0.0.6
版本號最好帶上,不帶版本號,可能會出錯!
安裝好了之后NinjectWebCommon.cs文件就會出現。這時候需要為該類中的RegisterServices方法添加代碼(注冊依賴解析器)
RegisterServices方法代碼如下:


private static void RegisterServices(IKernel kernel){System.Web.Mvc.DependencyResolver.SetResolver(new EssentialTools.Infrastructure.NinjectDependencyResolver(kernel));}
?
對瀏覽器發出請求到控制器處理請求這段時間發生的事!
1、瀏覽器向MVC框架發送一個請求Home的URL,MVC框架推測出該請求意指Home控制器,于是會創建HomeController類實例。
2、MVC框架在創建HomeController類實例過程中會發現其構造器有一個對IValueCalculator接口的依賴項,于是會要求依賴項解析器對此依賴項進行解析,?將該接口指定為依賴項解析器中的GetService方法所使用的類型參數。
3、依賴項解析器會將傳遞過來的類型參數交給TryGet方法,要求Ninject創建一個新的HomeController接口實例。
4、Ninect會檢測到HomeController構造器與其實現類LilnqValueCalculator具有綁定關系,于是為該接口創建一個LinqValueCalculator類實例,并將其回遞給依賴項解析器。
5、依賴項解析器將Ninject所返回的LilnqValueCalculator類作為IValueCalculator接口實現類實例回遞給MVC框架
6、MVC框架利用依賴項解析器返回的接口類實例創建HomeController控制器實例,并使用該控制器實例對請求進行服務。
?
為已經能夠正常運行的程序添加功能:為購物車內的東西打折。
在Models文件夾內添加一個叫做Discount的類
?


using System; using System.Collections.Generic; using System.Linq; using System.Web;namespace EssentialTools.Models {public interface IDiscountHelper{decimal ApplyDiscount(decimal totalParam);}public class DefaultDiscounter : IDiscountHelper{public decimal DiscountSize { get; set; }public decimal ApplyDiscount(decimal totalParam){return (totalParam - (DiscountSize / 100m * totalParam));}} }
?
這個類里面包涵了一個接口,沒有讓接口和類進行分離(當然,這不是重點)。
?
更改后的計算價格的類LinqValueCalculator


using System; using System.Collections.Generic; using System.Linq; using System.Web;namespace EssentialTools.Models {public class LinqValueCalculator : IValueCalculator{private IDiscountHelper discounter;public LinqValueCalculator(IDiscountHelper discountParam){discounter = discountParam;}public decimal ValueProducts(IEnumerable<Product> products){return discounter.ApplyDiscount(products.Sum(p => p.Price));}} }
最后更改依賴項解析器類中的AddBindings方法
private void AddBindings(){kernel.Bind<IValueCalculator>().To<LinqValueCalculator>();kernel.Bind<IDiscountHelper>().To<DefaultDiscounter>().WithPropertyValue("DiscountSize", 50M);}
在Discount類中,有一個DiscountSize的屬性,上面方法中使用了WithPropertyValue方法為這個屬性賦了初始值。
?