Using StructureMap with the ASP.NET MVC framework

 原文地址:http://www.bengtbe.com/blog/post/2009/02/27/Using-StructureMap-with-the-ASPNET-MVC-framework.aspx


Using StructureMap with the ASP.NET MVC framework


2009-02-27 星期五 作者:bengtbe

在這裏我要闡述的是怎麼用.net frameword 框架下的StructureMap這個類.  
在學習這個之間你需要對ASP.NET MVC框架,依賴注入和控制反轉有基本的瞭解。
這些技術也不只用於 StructureMap ,如果你喜歡這些,那麼你當然也用其它的DI/Ioc  工具了。

我們就用這個UserController 例子還說起,它有一個屬性IUserService 來調用控制層的服務,當

然IUserService 本身也會調用 IUserPepository 這個在數據層的方法。這個UserController 用

控制反轉來訪問IUserService ,這就是說這個UserService 類就是選用控制反轉來注入

UserController 實例化IUserService;
public class UserController : Controller
{
    private readonly IUserService m_UserService;
    public UserController(IUserService userService)
    {
        m_UserService = userService;
    }
    public ActionResult Edit(int id)
    {
        return View(m_UserService.GetById(id));
    }
}
這就叫容器注入,如果你就這樣寫而沒有寫其它的配置文件那麼你將得到如下的錯誤:
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 No parameterless constructor defined for this object.

Description: An unhandled exception occurred during the execution of the current web

request. Please review the stack trace for more information about the error and where

it originated in the code.

Exception Details: System.MissingMethodException: No parameterless constructor defined

for this object.  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
其實默認的,這個ASP.NET MVC framework 是需要一個構造函數的,一種方法是構造形式如下:
public UserController() : this(new UserService(new UserRepository()))
{
}
上面的代碼運行時就是調用這個來構造的。你要解決上錯的錯誤可以重寫這個構造函數,這種方式

叫Poor Man's Dependency Injection(不明智人選擇的次等辦法),如果知道DI/Ioc你會另有所選

.
上面的方法還有一個很大的缺點(這個我深有體會^^_^^)就是你把這個接口寫死了就是用

UserService 初始化 IUserService ,同理你也許用同樣的方法來處理 UserService 中的

UserRepository .這樣就把視圖層和數據層聯繫起來了。這時如果UserRepository 再有幾個屬性

的話,就有看頭了,好像那樣寫代碼寫醜了一點兒。。。

言歸正轉我們來用這個StructureMap 的ObjectFactory 來實現相同的效果吧,(初始化

IuserService)代碼如下:
public UserController() : this(ObjectFactory.GetInstance<IUserService>())
{
}
很簡單的代碼!這樣這個屬性就被初始化了,然而這時每個Controller 都要這樣才能達到效果,有

沒有更簡單的方法呢?讓我們來達到儘量簡化的目地。
ASP.NET MVC framework 用這個factory 參數來初始化controllers,還提供了一個基類
DefaultControllerFactory 讓你更加自由的初始化controller:
public class StructureMapControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        if(controllerType == null) return null;
        try
        {
            return ObjectFactory.GetInstance(controllerType) as Controller;
        }
        catch (StructureMapException)
        {
            System.Diagnostics.Debug.WriteLine(ObjectFactory.WhatDoIHave());
            throw;
        }
    }
}
當我們每次調用controller 時就會調用這個方法.上面這段代碼就是MstrutureMap的
ObjectFactory 來定製Controller的過程即使你的類中不只一個接口時也沒有關係,它會自動初始

化所有這種接口屬性;
現在我告訴你可以把這段代碼加入以 Global.asax.cs 當中當程序運行時就加載它。如下:
protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);
    StructureMapConfiguration.Configure();
    ControllerBuilder.Current.SetControllerFactory(new
      StructureMapControllerFactory());
}
最後一行這是我們告訴framework用我們定製的factory來代替默認的。現在你可以把Constructor

初始化的參數去年了吧,讓StrutureMap來幫你.

StrutureMap的構造
看到上面代碼的第二行了嗎?它就是用來構造StrutureMap的。它會構建一個新的StrutureMap 不

需要xml來配置。
public class StructureMapConfiguration
{
    public static void Configure()
    {
        ObjectFactory.Initialize(InitializeStructureMap);
    }
    private static void InitializeStructureMap(IInitializationExpression x)
    {
        x.Scan(y =>
                   {
                      y.Assembly("MvcWithNHibernate.Repositories");
                       y.Assembly("MvcWithNHibernate.Services");
                      y.With<DefaultConventionScanner>();
                   }
            );



http://stackoverflow.com/questions/1183124/how-do-i-mock-httpresponsebase-end
    }
}
你可以學習一下DefaultConventionScanner的用法,這個 scanner 是用來記錄哪些接口對應哪些類

來初始化的。比如 UserService 用來初始化IUserService ,UserRepository 來初始化

IUserRepository。
總結:
在這裏我們介紹瞭如何在ASP.NET MVC framework.框架下用StructureMap,我也介紹了怎麼樣利用

controller factory 來簡化你的代碼,一般情況下,在一開始就應用 Objectfactory 利用這種方

法可以減少不少代碼。在這裏只是介紹了在controller 層應用Objectfactory (其他的地方也可

以用了);

我在上面也是簡單的寫了一些代碼,介紹了一些常見的應用,(以下不會翻譯了,大致意思是你還

可以控制接口和類對應關係)

 

(這個我已經試過很好用的,還發現了一點就是類的構造參數有接口的它會初始成註冊的方法,會優先調用有接口的初始化。但是沒有試如果有兩個以上有參數的它怎麼處理?我想應該按參數最多的那個初始化吧!還沒有試,有時間的話就去試一試。)

發佈了12 篇原創文章 · 獲贊 3 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章