如何在 ASP.NET MVC 框架中使用 Unity 容器
本文解释了如何在 ASP.NET MVC 框架中使用 Unity IoC 容器。
引言
过去,我写过一篇关于 如何在 ASP.NET 中使用 Unity 容器 的文章。
在本文中,我将展示并解释如何在 ASP.NET MVC 框架 中使用 Unity IoC 容器,以便使我们应用程序中的各个方面更加解耦。
构建容器
就像在之前的文章中一样,首先要做的是构建容器本身。我将使用与之前的文章中相同的方法,以便在应用程序执行期间持久化 Unity 容器的状态。放置 Unity 容器的正确位置是作为 Global.asax 文件的一部分,作为当前运行的 HTTP 应用程序的属性。我将使用过去使用过的相同接口,如下所示:
public interface IContainerAccessor
{
IUnityContainer Container { get; }
}
构建接口后,在 Global.asax 文件中的 Global
类中实现它。
public class MvcApplication : HttpApplication, IContainerAccessor
{
#region Members
private static IUnityContainer _container;
#endregion
#region Properties
/// <summary>
/// The Unity container for the current application
/// </summary>
public static IUnityContainer Container
{
get
{
return _container;
}
}
#endregion
#region IContainerAccessor Members
/// <summary>
/// Returns the Unity container of the application
/// </summary>
IUnityContainer IContainerAccessor.Container
{
get { return Container; }
}
#endregion
#region Application Events
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
InitContainer();
ControllerBuilder.Current.SetControllerFactory(typeof(UnityControllerFactory));
}
protected void Application_End(object sender, EventArgs e)
{
CleanUp();
}
#endregion
#region Methods
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
private static void InitContainer()
{
if (_container == null)
{
_container = new UnityContainer();
}
// Register the relevant types for the
// container here through classes or configuration
_container.RegisterType<IMessageService, MessageService>();
}
private static void CleanUp()
{
if (Container != null)
{
Container.Dispose();
}
}
#endregion
}
实现很简单。你为容器创建一个 getter,它是 HTTP 应用程序的成员。同样,在应用程序启动事件中,我在容器中注册所有相关的依赖项,并在应用程序结束时处理容器。
Unity 控制器工厂
Global.asax 的这个新实现中真正重要的变化是控制器工厂的设置,你需要提供它。控制器工厂的职责是为传入的 HTTP 请求实例化相关的控制器。你应该实现 IControllerFactory
接口,以便能够插入你的工厂实现。UnityControllerFactory
的代码如下:
public class UnityControllerFactory : IControllerFactory
{
#region IControllerFactory Members
public IController CreateController
(RequestContext requestContext, string controllerName)
{
IContainerAccessor containerAccessor =
requestContext.HttpContext.ApplicationInstance as IContainerAccessor;
Assembly currentAssembly = Assembly.GetExecutingAssembly();
var controllerTypes = from t in currentAssembly.GetTypes()
where t.Name.Contains(controllerName + "Controller")
select t;
if (controllerTypes.Count() > 0)
{
return containerAccessor.Container.Resolve
(controllerTypes.First()) as IController;
}
return null;
}
public void ReleaseController(IController controller)
{
controller = null;
}
#endregion
}
主要要做的是实现 IControllerFactory
接口的 CreateController
方法。我使用请求上下文参数来检索当前应用程序实例,并从中,使用 IContainerAccessor
接口获取 Unity 容器。我还需实例化相关的控制器类,这由 Unity 容器为我完成。
容器 将通过 Resolve
方法将依赖项注入到控制器中,我们将获得我们想要的 依赖注入 功能。
要注入的类
我还编写了一个 MessageService
,这是一个返回消息并继承自
声明 GetMessage
方法的 IMessageService
。
public interface IMessageService
{
string GetMessage();
}
public class MessageService : IMessageService
{
#region IMessageService Members
public string GetMessage()
{
return "Hello Controller!";
}
#endregion
}
控制器
这个难题的最后一部分是控制器类。我使用以下代码实现了 HomeCotroller
类:
[HandleError]
public class HomeController : Controller
{
#region Members
[Dependency]
public IMessageService MessageService { get; set; }
#endregion
#region Actions
public ActionResult Index()
{
ViewData["Message"] = MessageService.GetMessage();
return View();
}
public ActionResult About()
{
return View();
}
#endregion
}
UnityControllerFactory
会将 MessageService
属性的依赖项注入到相关的类中,就这么简单。为了运行这个,你必须创建一个新的 MVC 框架应用程序,添加我编写的类,并将提供的 HomeController
更改为我编写的实现。
摘要
让我们总结一下。我展示了一个如何在 ASP.NET MVC 框架 应用程序中使用 Unity 容器 的示例。这是一个非常简单的例子,可以帮助你开始在你的 MVC Web 应用程序中使用 Unity。
历史
- 2010年8月5日:初始发布