天天看點

在asp.net mvc4控制器中使用Autofac來解析依賴在asp.net mvc4控制器中使用Autofac來解析依賴

我們的代碼中打破(抽離)依賴無非是為了增強可維護性、可測試性和靈活性。在前面的文章我在MVC應用程式建立了一些嚴重的依賴性。HomeController執行個體化一個存儲庫。這個存儲庫調用外部系統(來擷取)資料。其情形是位于Windows Azure的存儲表。過于依賴于外部系統,單元測試将變得冗長繁瑣(甚至不可靠)。Jeremy Miller 關于一個好的單元測試的品質寫了一篇不錯的部落格中,他說:

但是在我們能做到這一點之前,我們首先需要重構出所有這些依賴項。為此,我們在這些依賴對象之間建立了一些小接口。然後我們配置一個IoC容器,負責注入适當的依賴關系以便于在需要的時候用到。在這個示例中,我們使用Autofac,但它也可以是任何其他的.NET的loc容器。

在這個例子中,我們有一個簡單的MVC 4應用程式用來列舉出奧運金牌的得主。這些都從一個SQL資料庫用Entity Framework檢索到的資料。資料檢索過程封裝在一個存儲庫中。但是在HomeController中通過建立一個GoldMedalWinnersRepository執行個體, 我們已經建立了一個永久的隐藏的依賴。

測試該控制器迫使我們使用/測試存儲庫邏輯。讓我們先解決這個依賴。為了打破與外部類之間的依賴,可以讓構造函數應該要求這些依賴項(作為參數傳入)。是以我們可以從HomeController中移除存儲庫的執行個體化,而改用構造函數傳入參數:

好的,現在構造函數明确闡述了它的所有依賴項。但是如果我們測試控制器我們仍然需要處理存儲庫調用資料庫的(邏輯)。為了使控制器的測試獨立于存儲庫(邏輯),我們需要傳遞一個虛拟存儲庫版本。這種方式我們完全控制對象的内部運作,而測試真正的控制器。要做到這一點,我們需要建立一個存儲庫的抽象;下面是接口:

稍後我們将看到,存儲庫的構造函數也有一個依賴項。它需要一個Entity Framework DbContext來正常運作。是以我們需要為此建立一個抽象(接口);IGoldMedalWinnersContext:

在讓我們的存儲庫(類)的構造函數要求一個這個接口的實作(作為傳入闡述),這樣我們就成功的解耦了。

這時我們可以傳入實作了接口的任何存儲庫類。在我們的單元測試中,很容易僞造,複制或模拟存儲庫和dbcontext(來做一個僞庫以便于排除資料庫的因素)。

這是很好的,但是我們在哪裡執行個體化存儲庫?為此,我們可以使用一個IoC容器。這個神奇的東西可以通過配置,在必要時,可為控制器提供合适的存儲庫庫時。在這個示例中,我們使用Autofac。我們可以很容易的從Nuget安裝 Autofac ASP.NET MVC3 Integration package。它還适用于MVC4并負責安裝所需的所有的我們的MVC應用程式需要的核心依賴。

一旦安裝,我們可以根據需要配置Autofac來解析所有依賴項。為了示範,我們在MVC項目的App_start檔案夾下建立一個配置類。它有一個靜态的名為RegisterDependencies Autofac的方法,在這裡我們可以啟用Autofac。

我們建立一個Autofac ContainerBuilder,然後調用RegisterControllers來(注冊整個) MVC程式集。這種方法用AutofacDependencyResolver注冊所有在應用程式的控制器。每當MVC要求通路控制器時,這個解析器就傳回适當的控制器。

然後我們調用RegisterType注冊 GoldMedalWinnersRepository。在這裡我們配置成:每當我們需要一個IGoldMedalWinnersRepository, Autofac必須傳回一個GoldMedalWinnersRepository的執行個體。我們将生命周期設定為了InstancePerHttpRequest。我們同樣的方式注冊了GoldMedalWinnersContext。我們建構的容器,并為我們的容器的AutofacDependencyResolver設定了解析器MVC DependencyResolver 。

在MVC應用程式中的全局的.asax檔案中,在所有其他MVC注冊之前,我們調用了IoC配置類的RegisterDependencies方法,這樣就可以了(我們準備好了)。

這就是全部(目前為止)。當我們啟動應用程式,Autofac會做一個事情然後為控制器提供适當的執行個體化了帶有适當的dbcontext的存儲庫。如果我們編寫單元測試,然而,Autofac不會為我們的控制器提供存儲庫,是以我們可以注入一些假的,副本或仿制版本。這正是我們需要的。