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 更糟糕。