使用 DI 在每个 MVC 请求上加载存储库实例
本文关键字:加载 存储 实例 请求 MVC DI 使用 | 更新日期: 2023-09-27 18:35:10
我在这篇文章中读到他们正在使用依赖注入来加载每个 mvc 请求上的存储库实例。
我不确定我是否正确理解,但我目前正在我的 mvc 应用程序中使用。 UserRepository
实现IUserRepository
接口。此接口注入到控制器构造函数中
public class UserController : Controller
{
private IUserRepository repository;
public UserController(IUserRepository rep)
{ repository = rep; }
public UserController() : this(new UserRepository()) {}
}
但我没有看到使用此接口(IUserRepository
)的任何好处,我可以在没有接口的情况下使用UserRepository
。显然,有人认为更聪明的人是正确的方法(我在 apress mvc4 书中找到了它),我恳请某人详细说明为什么这是更好的方法,而不是使用没有接口的存储库。
考虑到这一点,我会要求任何人分享有关如何实现此方法的具体示例或链接(使用依赖注入在每个 mvc 请求上加载存储库实例)。
DI 背后的主要思想是迫使你看到大局而不是具体的实现。
你的控制器需要获取用户,但它不应该关心具体的实现(你的仓库是从数据库、Web 服务、xml 文件等中获取用户,还是使用 Linq2Sql、EntityFramework、Dapper 或其他底层的东西)。
你的控制器依赖于可以在构造函数、属性或方法中注入的代码段,但它并不真正关心具体的实现。
DI 消除了控制器和存储库之间的紧密耦合,允许您通过模拟存储库来编写单元测试,并且您可以轻松地更改存储库的具体实现(例如,使用 PetaPoco 而不是 EntityFramework),而无需触及其余代码。
您还应该查看 SOLID 原则:http://en.wikipedia.org/wiki/SOLID_(对象oriented_design)
当我的团队开始使用依赖注入时,我们正在阅读Steven Sanderson的一本好书"Pro ASP.NET MVC 2 Framework"。在这本书中,他描述了如何使用Castle Windsor,一个流行的依赖注入框架。在另一本书"Pro ASP.NET MVC 3 Framework"中,据我所知,描述了如何使用Ninject(另一个框架)。
为了使用温莎城堡:
首先,您必须编写控制器工厂的自定义实现:
/// <summary>
/// Controller factory the class is to be used to eliminate hard-coded dependencies
/// between controllers and other components
/// </summary>
public class ControllerFactory : DefaultControllerFactory
{
private readonly IWindsorContainer container;
public WindsorControllerFactory(IWindsorContainer container)
{
this.container = container;
}
public override void ReleaseController(IController controller)
{
container.Release(controller.GetType());
}
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
return (IController)container.Resolve(controllerType);
}
}
然后,您必须为所有控制器编写安装程序。
/// <summary>
/// Castle windsor installer for controller components.
/// </summary>
public class ControllersInstaller : IWindsorInstaller
{
/// <summary>
/// Performs the installation in the <see cref="T:Castle.Windsor.IWindsorContainer"/>.
/// </summary>
/// <param name="container">The container.</param>
/// <param name="store">The configuration store.</param>
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Classes.FromThisAssembly()
.BasedOn<IController>()
.LifestyleTransient()
);
}
}
如果您希望将存储库解析为依赖项,则还应为它们编写安装程序。它将类似于ControllersInstaller,但生活方式将是LifestylePerWebRequest()。PerRequestLifestyle应该在web.config文件中注册。
<httpModules>
<add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" />
</httpModules>
然后,当应用程序在 Global.asax 中启动时,您必须创建一个容器实例.cs:
public class MvcApplication : System.Web.HttpApplication
{
private static IWindsorContainer container;
protected void Application_Start()
{
container = new WindsorContainer();
container.Install(FromAssembly.This());
//Set the controller builder to use our custom controller factory
var controllerFactory = new WindsorControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}
protected void Application_End()
{
container.Dispose();
}
}
还有一个指向温莎城堡文档的链接,您可以在其中找到有关使用生活方式和 ASP.NET MVC 3 应用程序教程的更多信息。
** 使用接口时
- 在代码中模拟依赖项更容易(一些模拟框架有限制)
- 开发新实现并测试它更容易,而无需更改旧实现。
** 如果已实现和设置控制器工厂,则不需要控制器中的默认构造函数。
接口的主要优点是它们鼓励抽象。如果你想模拟一个完全不同的实现(例如,在执行单元测试时,无论如何都应该:)这样做,你只需将IUserRepository
的另一个实现注入到你的UserController
构造函数。在我看来,这是使用接口的主要优势之一。