前言html
在以前的篇幅中,用文字和圖像來表示了控制器的激活過程,描述的角度都是從框架默認實現的角度去進行描述的,這樣也使得你們均可以清楚的知道激活的過程以及其中涉及到的對象模型,今天的篇幅就是在激活的過程當中,框架提供了哪些可注入點,站在一個使用者的角度來進行描述。c#
激活控制器-注入點入口框架
如上圖,這是上個篇幅中描述的控制器激活過程圖,這裏引用過來是怕有的朋友忘記了前面的所說和沒看過前面篇幅的朋友。ide
就從默認控制器工廠的實現來看,在CreateController()方法中,經過GetControllerType()方法來獲取控制器類型(Type),而後傳遞到GetControllerInstance()方法中,經過其中的實現來完成根據控制器類型(Type)到IController的生成。而在後續的注入點也是在GetControllerInstance()方法實現中來進行注入的,GetControllerInstance()方法便是整個控制器激活過程的入口點。函數
IoC示例ui
既然說到了動態注入,想必就要用到IoC框架了,在MVC學前篇中提到過Ninject的使用,下面這個示例即是依賴於Ninject的來作的演示:spa
1 /// <summary> 2 /// 產品實體類 3 /// </summary> 4 public class Product 5 { 6 public string ID { get; set; } 7 public string Name { get; set; } 8 }
定義一個數據實體類沒什麼好說的,htm
1 /// <summary> 2 /// 抽象數據提取庫 3 /// </summary> 4 public interface IDataStandard 5 { 6 List<Product> GetProducts(); 7 } 8 /// <summary> 9 /// 默認實現--數據提取庫 10 /// </summary> 11 public class DataProvide : IDataStandard 12 { 13 14 public List<Product> GetProducts() 15 { 16 List<Product> products = new List<Product>() 17 { 18 new Product(){ ID="1",Name="name1"}, 19 new Product(){ID="2",Name="name2"}, 20 new Product(){ID="3",Name="name3"} 21 }; 22 return products; 23 } 24 }
這裏定義的一個是抽象的數據提取庫,和一個默認的實現做爲演示用於提供數據用的。對象
1 /// <summary> 2 /// 抽象數據調用 3 /// </summary> 4 public interface IDataCall 5 { 6 void WriterToMonitor(); 7 } 8 9 /// <summary> 10 /// 默認的數據調用實現 11 /// </summary> 12 public class DefultDataCall:IDataCall 13 { 14 private IDataStandard _DataStandard; 15 16 public DefultDataCall(IDataStandard dataStandard)//使用構造函數方式注入 經過Ninject框架實現 17 { 18 _DataStandard = dataStandard; 19 } 20 21 public void WriterToMonitor() 22 { 23 foreach(var data in _DataStandard.GetProducts()) 24 { 25 Console.WriteLine("Prodcut ID:" + data.ID + " Name:" + data.Name); 26 } 27 } 28 }
這裏定義的是抽象的數據調用和默認的實現,咱們如今要作的就是經過IoC框架來讓調用客戶端對數據調用和數據提取解耦,路由
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 IKernel ninject = new StandardKernel(); 6 ninject.Bind<IDataStandard>().To<DataProvide>(); 7 IDataCall dataCall = ninject.Get(typeof(DefultDataCall)) as IDataCall; 8 if (dataCall != null) 9 { 10 dataCall.WriterToMonitor(); 11 } 12 13 Console.ReadLine(); 14 } 15 }
運行這段代碼:
很簡單明瞭的一個示例,在MVC的項目中也是這樣運行的。
MVC項目中的運用
在上面的章節裏說過,入口點在protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType);方法中,咱們只須要實現一個默認的控制器工廠類型,而且重寫一下這個方法,由於咱們已經能夠在重寫的方法中獲取到控制器的類型了,有了它就能夠按照IoC示例中的那樣來進行其它對象到控制器的一個動態注入。
咱們先要定義一個控制器,而且要讓它對上述示例中的抽象提取庫依賴,採起構造函數式注入(依賴)。
看一下示例:
1 public class IoCDemoController : Controller 2 { 3 // 4 // GET: /IoCDemo/ 5 6 private IDataStandard _DataStandard; 7 8 public IoCDemoController(IDataStandard dataStandard) 9 { 10 _DataStandard = dataStandard; 11 } 12 13 public ActionResult Index() 14 { 15 return View(_DataStandard.GetProducts()); 16 } 17 }
在Index方法上右鍵,點擊添加視圖:
點擊添加,而且在視圖中輸入以下代碼:
@model IEnumerable<ConsoleApplication2.Product> @{ ViewBag.Title = "Index"; } <h2>Index</h2> @foreach (var item in Model) { <h3>ID: @item.ID Name:@item.Name</h3> }
再把Global.asax文件中的路由設置修改一下:
1 routes.MapRoute( 2 "Default", // 路由名稱 3 "{controller}/{action}/{id}", // 帶有參數的 URL 4 new { controller = "IoCDemo", action = "Index", id = UrlParameter.Optional } // 參數默認值 5 );
這個時候準備工做都作好,但是控制器中所用的數據哪裏來呢?從咱們默認實現的控制器工廠中來:
1 public class NinjectControllerFactory :DefaultControllerFactory 2 { 3 private IKernel _NinjectKernel; 4 5 public NinjectControllerFactory() 6 { 7 _NinjectKernel = new StandardKernel(); 8 _NinjectKernel.Bind<IDataStandard>().To<DataProvide>(); 9 } 10 11 protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) 12 { 13 IController controller = _NinjectKernel.Get(controllerType) as IController; 14 if (controller != null) 15 { 16 return controller; 17 } 18 return null; 19 } 20 21 }
按照上面章節中的樣式,在NinjectControllerFactory中事先綁定數據類型,等到系統執行須要用到控制器的時候會經過Ninject框架來說數據動態的注入到控制器中。
最後還要設置一項:
在Global.asax文件中的Application_Start()方法中要把咱們默認的實現的控制器工廠設置到MVC框架中,
1 protected void Application_Start() 2 { 3 AreaRegistration.RegisterAllAreas(); 4 5 RegisterGlobalFilters(GlobalFilters.Filters); 6 RegisterRoutes(RouteTable.Routes); 7 ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); 8 }
添加上代碼的最後一句。如今咱們就能夠來看一下最終效果了。
本篇就講到這裏,會在下個篇幅中繼續講解其餘的注入點。