ASP.NET MVC 2擴展點之Controller Factory

作者: 麒麟  來源: 博客園  發布時間: 2010-08-02 14:07  閱讀: 2325 次  推薦: 0   原文鏈接   [收藏]  

  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,而且你還會得到下面這個錯誤,如下圖:

hhh

  產生上面錯誤的原因是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();
    }
}

  運行結果如下:

hhhk  總結:本文簡單的介紹了一下自定義Controller Factory。

  參考:asp.net mvc 2 in action

0
0
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()