Autofac,MVC 控制器的动态依赖注入
Autofac, dynamic dependency Injection for MVC controllers
我有一个带有 UnitOfWork 接口和管理器的项目设置。当我只需要使用 accountMananger 作为我的控制器的基础时,所有这些都运行良好。
protected BaseController(IAccountManager acctManager)
{
_accountManager = acctManager;
}
我的控制器是这样创建的,并且可以正常工作。
public class AccountController : BaseController
{
public AccountController(IAccountManager accountManager)
: base(accountManager)
{
}
现在我正在创建其他业务经理,我意识到到项目结束时,我的 BaseController 构造函数将变得非常庞大,或者我将加载大量基于我所使用的控制器的各种签名。如果我忘记了什么并且需要另一个管理器并更改一个构造函数,则所有其他控制器也需要更改。
我的意思是,我实际上一直希望 accountManager 在基础中成为 injected/resolved。我可以这样做吗?由于我99%正在检查授权。
我读过有关 ControllerFactories 的文章,但也有人提到要实现 IDependancyResolver
,但没有示例,这是他首选的实现方式。
我认为这会成为基于我需要的控制器创建构造函数的一大负担,而我还没有。
任何人都可以给我一个例子,说明如何在我需要时轻松地联系我在基地的经理。我的意思是,它们都已创建并准备好被解决。所以我到底为什么需要以如此奇怪的方式传递它们?
对不起。只是学习 DI,这是一个很好的教程,但正如您所看到的,缺少一些进一步的解释。
您与客户经理之间的关系称为 Cross-Cutting Concern。有几种不同的方法可以为这只猫设置皮肤,但您应该避免将相同的依赖项注入每个控制器。
一般来说,最好避免继承,因为这会导致 类 之间的紧密耦合。紧耦合在这里是显而易见的——如果你以后需要一个没有 IAccountManager
作为依赖项的控制器怎么办?
在这种特殊情况下,您可以使用 MVC 中内置的松耦合授权框架 - AuthorizeAttribute,这是处理对控制器操作方法的访问的正常方式。
[Authorize]
public class AccountController : Controller
{
public AccountController () { . . . }
[AllowAnonymous]
public ActionResult Register() { . . . }
public ActionResult Manage() { . . . }
public ActionResult LogOff() { . . . }
}
还有几个其他选项可用于实现横切关注点 - 实现 IActionFilter
- see this for a DI friendly example, interception (which some DI containers support), using the Decorator Pattern,并将依赖项置于环境上下文中(例如 HttpContext.Items)。
I can see this becoming a big burden to create constructors based on the controllers I need, which I dont have yet.
这就是为什么您应该继承 DefaultControllerFactory
并在应用程序启动时(在 composition root 中)为其提供 DI 容器的一个实例。为您的控制器提供依赖项通常是容器的责任,尤其是当您的应用程序很大时。
public class AutofacControllerFactory
: DefaultControllerFactory
{
private readonly IContainer container;
public InjectableControllerFactory(IContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
this.container = container;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (requestContext.HttpContext.Request.Url.ToString().EndsWith("favicon.ico"))
return null;
return controllerType == null ?
base.GetControllerInstance(requestContext, controllerType) :
this.container.Resolve(controllerType) as IController;
}
}
我强烈建议您阅读这本书 Dependency Injection in .NET。 DI 是软件开发中最容易被误解的概念之一,值得投资自己详细研究该主题,而不必筛选 Internet 上的错误信息。正确使用 DI 可以获得很多好处,但使用不当往往比根本不使用 DI 更糟糕。
我有一个带有 UnitOfWork 接口和管理器的项目设置。当我只需要使用 accountMananger 作为我的控制器的基础时,所有这些都运行良好。
protected BaseController(IAccountManager acctManager)
{
_accountManager = acctManager;
}
我的控制器是这样创建的,并且可以正常工作。
public class AccountController : BaseController
{
public AccountController(IAccountManager accountManager)
: base(accountManager)
{
}
现在我正在创建其他业务经理,我意识到到项目结束时,我的 BaseController 构造函数将变得非常庞大,或者我将加载大量基于我所使用的控制器的各种签名。如果我忘记了什么并且需要另一个管理器并更改一个构造函数,则所有其他控制器也需要更改。
我的意思是,我实际上一直希望 accountManager 在基础中成为 injected/resolved。我可以这样做吗?由于我99%正在检查授权。
我读过有关 ControllerFactories 的文章,但也有人提到要实现 IDependancyResolver
,但没有示例,这是他首选的实现方式。
我认为这会成为基于我需要的控制器创建构造函数的一大负担,而我还没有。
任何人都可以给我一个例子,说明如何在我需要时轻松地联系我在基地的经理。我的意思是,它们都已创建并准备好被解决。所以我到底为什么需要以如此奇怪的方式传递它们?
对不起。只是学习 DI,这是一个很好的教程,但正如您所看到的,缺少一些进一步的解释。
您与客户经理之间的关系称为 Cross-Cutting Concern。有几种不同的方法可以为这只猫设置皮肤,但您应该避免将相同的依赖项注入每个控制器。
一般来说,最好避免继承,因为这会导致 类 之间的紧密耦合。紧耦合在这里是显而易见的——如果你以后需要一个没有 IAccountManager
作为依赖项的控制器怎么办?
在这种特殊情况下,您可以使用 MVC 中内置的松耦合授权框架 - AuthorizeAttribute,这是处理对控制器操作方法的访问的正常方式。
[Authorize]
public class AccountController : Controller
{
public AccountController () { . . . }
[AllowAnonymous]
public ActionResult Register() { . . . }
public ActionResult Manage() { . . . }
public ActionResult LogOff() { . . . }
}
还有几个其他选项可用于实现横切关注点 - 实现 IActionFilter
- see this for a DI friendly example, interception (which some DI containers support), using the Decorator Pattern,并将依赖项置于环境上下文中(例如 HttpContext.Items)。
I can see this becoming a big burden to create constructors based on the controllers I need, which I dont have yet.
这就是为什么您应该继承 DefaultControllerFactory
并在应用程序启动时(在 composition root 中)为其提供 DI 容器的一个实例。为您的控制器提供依赖项通常是容器的责任,尤其是当您的应用程序很大时。
public class AutofacControllerFactory
: DefaultControllerFactory
{
private readonly IContainer container;
public InjectableControllerFactory(IContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
this.container = container;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (requestContext.HttpContext.Request.Url.ToString().EndsWith("favicon.ico"))
return null;
return controllerType == null ?
base.GetControllerInstance(requestContext, controllerType) :
this.container.Resolve(controllerType) as IController;
}
}
我强烈建议您阅读这本书 Dependency Injection in .NET。 DI 是软件开发中最容易被误解的概念之一,值得投资自己详细研究该主题,而不必筛选 Internet 上的错误信息。正确使用 DI 可以获得很多好处,但使用不当往往比根本不使用 DI 更糟糕。