Asp.net mvc2中提供很多可以擴充的地方,利用這些擴充之後,asp.net mvc使用起來更加靈活。Simone Chiaretta曾寫過一篇文章:13 ASP.NET MVC extensibility points you have to know。文章中概括性的介紹了13個asp.net mvc開發人員必須知道的擴充點。我將從這13個擴充點中挑選幾個常見的重要的擴充點進行詳細的介紹。這篇將文章將首先介紹Controller Factory。
Controller Factory是Asp.MVC架構中一個重要的擴充點。Controller Factory是用來建立控制器。而Controller最常用的情境之一是支援依賴注入。但是如果直接在控制器中使用依賴注入,預設情況下asp.net mvc架構將不會為你建立Controller,而且你還會得到下面這個錯誤,如:
產生上面錯誤的原因是DefaultControllerFactory使用Activator.CreateInstance來初始化控制器,而這個方法對你依賴注入的參數一無所知。
這種情況下,我們就要使用自訂的Controller Factory。
一個自訂的Controller Factory需要繼承IControllerFactory或者繼承過IControllerFactory的類,如:DefaultControllerFactory。下面代碼是一個自訂的Controller factory。
public class MyCustomControllerFactory : DefaultControllerFactory{ protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { /* implement controller creation logic */ return base.GetControllerInstance(requestContext, controllerType); }}
在定義Controller Factory之後,需要在Application_Start()中註冊一下:
ControllerBuilder.Current.SetControllerFactory(new MyCustomControllerFactory());
這樣MVC架構將會使用你自定的Controller Factory建立Controller。
看下面這個ProductsController,這個控制器在建構函式中接受依賴注入
public class ProductsController : Controller{ public ProductsController(IProductRepository repository,IShippingCalculator shippingCalculator, ITaxService taxService) { /* ... */ } /* ... */}
如果自己手動寫代碼建立這樣的Controller是非常乏味的。幸運的是我們不需要自己手寫代碼去實現。因為存在很多IoC工具供我們使用。在.net中最好的依賴注入工具之一便是StructureMap,它是一個輕量級開源免費IOC架構。下面我將使用這個工具實現一個簡單的MVC中依賴注入的Demo。
1、到http://structuremapsourceforge.net/上下載這個工具。在MVC項目中引用StructureMap.dll。
2、在Models中定義一個依賴注入的IMessageProvider介面,以及它的一個實作類別StructureMapMessageProvider。
namespace MvcApplication1.Models{ public interface IMessageProvider { string GetMessage(); } public class StructureMapMessageProvider : IMessageProvider { public string GetMessage() { return "This message was provided by StructureMap"; } }}
3、利用StructureMap自訂的Controller Factory代碼如下:
public class StructureMapControllerFactory : DefaultControllerFactory{ protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) { return ObjectFactory.GetInstance(controllerType) as IController; }}
4、定義一個靜態類StructureMapBootstrapper,用來初始化StructureMap和設定StructureMapControllerFactory為項目的Controller Factory,代碼如下:
public static class StructureMapBootstrapper{ public static void Initialize() { ObjectFactory.Initialize(x => x.AddRegistry(new MyStructureMapApplicationRegistry())); } public static void SetControllerFactory() { var controllerFactory = new StructureMapControllerFactory(); ControllerBuilder.Current.SetControllerFactory(controllerFactory); }}
5、在Global.asax中使用上面的StructureMapBootstrapper類設定Controller Factory和初始化StructureMap。
StructureMapBootstrapper.SetControllerFactory();StructureMapBootstrapper.Initialize();
6、這樣我們就能正常使用了。我們將HomeController設定如下:
[HandleError]public class HomeController : Controller{ private IMessageProvider _messageProvider; public HomeController(IMessageProvider messageProvider) { _messageProvider = messageProvider; } public ActionResult Index() { ViewData["Message"] = _messageProvider.GetMessage(); return View(); }}運行結果如下:
總結:本文簡單的介紹了一下自訂Controller Factory。下一篇文章將介紹ModelBinder。
參考:asp.net mvc 2 in action