依賴注入(DI)與控制反轉(IoC)是企業級應用架構的核心模式。本講將實際展示如何在專案中整合 Unity 2.x 容器,採用建構函式注入與執行時期注入方式,並提供完整原始碼下載。
可從 CodePlex 或 NuGet 取得 Unity 2.x。在方案中建立 App.Core 核心類別庫,參考 Microsoft.Practices.Unity.dll、System.Web.Mvc、System.Web 以及專案內的 BLL、IBLL、DAL、IDAL 等介面與實作專案。
using System;
using Microsoft.Practices.Unity;
using App.BLL;
using App.DAL;
using App.IBLL;
using App.IDAL;
namespace App.Core {
public class DependencyRegisterType {
public static void Container_Sys(ref UnityContainer container) {
container.RegisterType<ISysSampleBLL, SysSampleBLL>();
container.RegisterType<ISysSampleRepository, SysSampleRepository>();
}
}
}
實作 IDependencyResolver 介面,管理每個 HTTP 請求的子容器生命週期:
using System;
using System.Web;
using System.Web.Mvc;
using Microsoft.Practices.Unity;
namespace App.Core {
public class UnityDependencyResolver : IDependencyResolver {
private const string HttpContextKey = "perRequestContainer";
private readonly IUnityContainer _container;
public UnityDependencyResolver(IUnityContainer container) {
_container = container;
}
public object GetService(Type serviceType) {
if (typeof(IController).IsAssignableFrom(serviceType)) {
return ChildContainer.Resolve(serviceType);
}
return IsRegistered(serviceType) ? ChildContainer.Resolve(serviceType) : null;
}
public IEnumerable<object> GetServices(Type serviceType) {
if (IsRegistered(serviceType)) {
yield return ChildContainer.Resolve(serviceType);
}
foreach (var service in ChildContainer.ResolveAll(serviceType)) {
yield return service;
}
}
protected IUnityContainer ChildContainer {
get {
var childContainer = HttpContext.Current.Items[HttpContextKey] as IUnityContainer;
if (childContainer == null) {
HttpContext.Current.Items[HttpContextKey] = childContainer = _container.CreateChildContainer();
}
return childContainer;
}
}
public static void DisposeOfChildContainer() {
var childContainer = HttpContext.Current.Items[HttpContextKey] as IUnityContainer;
if (childContainer != null) childContainer.Dispose();
}
private bool IsRegistered(Type typeToCheck) {
var isRegistered = true;
if (typeToCheck.IsInterface || typeToCheck.IsAbstract) {
isRegistered = ChildContainer.IsRegistered(typeToCheck);
if (!isRegistered && typeToCheck.IsGenericType) {
var openGenericType = typeToCheck.GetGenericTypeDefinition();
isRegistered = ChildContainer.IsRegistered(openGenericType);
}
}
return isRegistered;
}
}
}
在 Application_Start 中建立容器、註冊類型並設定 Dependency Resolver:
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using App.Core;
using Microsoft.Practices.Unity;
namespace App.Admin {
public class MvcApplication : System.Web.HttpApplication {
protected void Application_Start() {
AreaRegistration.RegisterAllAreas();
// ... 其他初始化 ...
var container = new UnityContainer();
DependencyRegisterType.Container_Sys(ref container);
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
}
完整專案原始碼可至:Microsoft.Practices.Unity.rar