上上一篇分層架構系列文章「ASP.NET MVC 專案分層架構 Part.6 - DI/IoC 使用 Unity.MVC」 介紹了如何在一個 ASP.NET MVC 4 的分層架構專案中使用 Unity.MVC4 實作 DI/IoC,不管是 Unity.MVC3 or Unity.MVC4 都是使用了 Enterprise Library Unity Application Block 2.1 版 ( Unity.MVC3 為 2.1.505.0, Unity.MVC4 為 2.1.505.2 ),然而就在 2013-04-26 的時候 Enterprise Library 6.0 正式 Release 了,而 Unity Application Block 也進展到 3.0 版。
此次 EntLib 6.0 增加了兩個 Application Block,而既有的 Application Block 也有很多的更新功能,而其中一點就是 Unity Application Block 加強了對 ASP.NET MVC 與 ASP.NET Web API 的技術整合,另外也推出了自家官方的 ASP.NET MVC, ASP.NET Web API 整合組件,在 NuGet 就可以取得、安裝,這一篇就用之前分層架構的程式來介紹如何在 ASP.NET MVC 4 網站裡使用 Unity bootstrapper for ASP.NET MVC。
之前我們所使用的 Unity.MVC4,這是給 ASP.NET MVC 4 網站所使用的,
而 ASP.NET MVC 3 網站則是可以用 Unity.MVC3,
以上兩個 Unity.MVC 都是使用 Unity Application Block 2.1,雖然不是 EntLib 官方所推出,但還是相當容易使用。
Unity Application Block 3
http://msdn.microsoft.com/en-us/library/dn170416.aspx
The new Unity Application Block includes many improvements:1. Registration by convention.
2. Support for NetCore (Windows Store apps).
3. Resolving objects of type Lazy<T>.
4. The Unity assembly is now Security Transparent.
5. Support for ASP.NET MVC and ASP.NET Web API.
我建議各位可以先下載文件檔,從文件裡了解如何使用 Unity 3,文件的下載位置如下:
https://entlib.codeplex.com/releases/view/64243
文件內容算是相當完整,不單只有 ASP.NET MVC(這只佔其中一部分而已),其他的包含有 ASP.NET Web API, WCF, ASP.NET WebForm 等其他技術的整合使用說明,另外對 EntLib 其他 Application Block 有興趣的朋友也可以下載另外的兩個文件檔。
Unity bootstrapper for ASP.NET MVC
以往在 ASP.NET MVC 網站裡想要使用 Unity 來實作 DI/IoC,除了透過 Unity.MVC 的安裝來使用之外,就是要自己手動的方式來完成,而現在 EntLib Unity 也推出了官方版的整合組件「Unity bootstapper for ASP.NET MVC」,在 Visual Studio 裡透過 NuGet 就可以輕鬆安裝。
P.S.
直接在 NuGet 搜尋列裡輸入「Unity bootstrapper for ASP.NET MVC」,可能要在查詢結果裡案好幾次下一頁才能看到,這邊告訴各位可以在關鍵字的前後加上雙引號,這樣就可以直接尋找有完全符合的結果,就跟我們在 Google 裡要搜尋含有限定字詞的操作一樣。
不過這邊要特別提醒,Enterprise Library 6.0 僅能安裝在使用 .NET 4.5 的專案裡,而 Unity bootstrapper for ASP.NET MVC 更限定只能在 ASP.NET MVC 4 以上的版本才能使用,所以要特別注意。
安裝完成之後,組件參考會多增加三個項目,
另外在 ~/App_Start 目錄下增加了兩個檔案,分別是:UnityConfig.cs, UnityMvcActivator.cs
首先來看看 UnityConfig.cs 的內容,
using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
namespace Mvc_Repository.Web.App_Start
{
/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
/// <summary>Registers the type mappings with the Unity container.</summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to
/// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
// container.LoadConfiguration();
// TODO: Register your types here
// container.RegisterType<IProductRepository, ProductRepository>();
}
}
}
上面用 region 包起來的部分,基本上是很少會去更動到,而下面的靜態方法 RegisterTypes(),這就是我們要註冊型別的地方,這邊就輸入我們要註冊的類別內容,而至於另一個檔案 UnityMvcActivator.cs,這個檔案要修改的機會也不多,但如果像在系統裡對於使用 Unity 註冊的類別在一次的 HTTP Request 範圍中做 Singleton 管理的話,那麼就會需要動到這個程式了(UnityMvcActivator.cs),在我這次的示範並不會對此檔案做任何變動,
using System.Linq;
using System.Web.Mvc;
using Microsoft.Practices.Unity.Mvc;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Mvc_Repository.Web.UnityWebActivator), "Start")]
namespace Mvc_Repository.Web
{
/// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary>
public static class UnityWebActivator
{
/// <summary>Integrates Unity when the application starts.</summary>
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
}
}
基本上這樣就可以了,基本的動作就是只需要在 UnityConfig.cs 的 RegisterTypes() 靜態方法內加入要註冊的類別就完成,其餘什麼修改 Global.asax 等動作都不用了,這是因為在 UnityMvcActivator.cs 裡面使用了 WebActivator,對於 WebActivator 想要有詳細的了解與說明,黑大(黑暗執行緒)的部落格裡就有一篇文章在做介紹,
WebActivator - 不修改Global.asa也能加入Application_Start - 黑暗執行緒
基本上完成上面的步驟之後就完成了。
小插曲
完成上面的步驟之後,我就在 VS2012 裡按下 F5 執行網站,但卻看到了以下的錯誤,
問題就在下面的地方,
在 GenericRepository.cs 裡有兩個建構式是有傳入參數的,雖然說兩個傳入參數的型別不同,但是對於 Unity 來說,這兩個沒辦法去分別呀,因為建構式的傳入參數個數都一樣,在 Unity 去做型別註冊時就根本不知道該用哪一個建構式,所以先刪除另一個以 ObjectContext 為輸入參數的建構式,
但是做了上面的修改後去執行網站卻會發現以下的錯誤,
於是我決定把 GenericRepository 的基本建構式給移除,
再來的問題就是剩下的建構式,怎麼傳給它 DbContext 參數呢?
要解決這個步驟就是要到 UnityConfig.cs 的 RegisterTypes() 方法內,因為現在 Repository 與 Service 類別的建立都是交給 Unity 來處理,現在 GenericRepository 的建構式只剩下一個,而且要傳入一個 DbContext,所以在 UnityConfig.cs 的 RegisterTypes() 方法內處理 IRepository<T> 註冊的地方,讓類別建立實例的時候也傳入建構式所需要傳入的參數,基本上就是以下的內容,
在註冊 IRepository<T> 類別的時候,可以使用 InjectionConstructor 來傳入建立類別實例時所需要的建構式參數值,這樣就可以解決問題了。
專案使用 .NET Framework 4.5 以及 ASP.NET MVC 4.5 的朋友,不妨使用 Unity 來做為 DI/IoC 的解決方案,並且搭配 Unity bootstrapper for ASP.NET MVC 來使用,也是不錯的選擇。
相關連結:
Enterprise Library - MSDN
http://msdn.microsoft.com/library/cc467894.aspx
Enterprise Library 6 - April 2013
http://msdn.microsoft.com/zh-TW/library/dn169621.aspx
Microsoft Enterprise Library 6 - Microsoft Download Center
http://www.microsoft.com/en-us/download/details.aspx?id=38789
Enterprise Library 6 - April Document Download - patterns & practices – Enterprise Library
https://entlib.codeplex.com/releases/view/64243
Unity Container - MSDN
http://msdn.microsoft.com/en-us/library/dd203101.aspx
Unity 3 – April 2013
http://msdn.microsoft.com/en-us/library/dn170416.aspx
Microsoft Unity 3 - Microsoft Download Center
http://www.microsoft.com/en-us/download/details.aspx?id=38788
以上
沒有留言:
張貼留言