Autofac,MVC控制器的动态依赖注入

时间:2015-02-11 16:18:20

标签: c# asp.net-mvc dependency-injection autofac

我有一个使用UnitOfWork Interfaces和Managers的项目设置。所有这一切都很好,而我只需要使用accountMananger作为我的控制器的基础。

    protected BaseController(IAccountManager acctManager)
    {
        _accountManager = acctManager;
    }

我的控制器是这样创建的,并且有效。

  public class AccountController : BaseController
  {
    public AccountController(IAccountManager accountManager)
        : base(accountManager)
    {
    }

现在我正在创建其他业务经理,我意识到在项目结束时我的BaseController构造函数将会很大,或者我将根据我所在的控制器加载各种签名。如果我忘记了某些内容并需要另一个管理员并更改了一个构造函数,那么所有其他控制器也需要更改。

我的意思是,我实际上总是希望在基础中注入/解析accountManager。我能这样做吗?由于我99%检查授权。

我已经阅读过关于ControllerFactories的内容,但也有人提到要实现IDependancyResolver,但没有例子,这是他首选的方法。

我可以看到,基于我需要的控制器创建构造函数会成为一个很大的负担,我还没有。

任何机构都可以给我一个如何轻松访问基地经理的例子,因为我需要它们。我的意思是,无论如何,他们都创造并准备好解决..所以为什么我需要以一种奇怪的方式传递它们呢?

对不起。只是学习DI,这是一个很好的教程,但你可以看到缺乏一些进一步的解释。

1 个答案:

答案 0 :(得分:2)

您与帐户经理的相关信息称为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 - interceptionDecorator Pattern(某些DI容器支持),并将依赖项放在环境上下文中(例如HttpContext.Items)。

  

我可以看到,基于我需要的控制器创建构造函数会成为一个很大的负担,我还没有。

这就是为什么你应该继承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是软件开发中最容易被误解的概念之一,非常值得投资自己详细研究这个主题,而不必在互联网上筛选错误的信息。通过正确使用DI可以获得许多好处,但使用不当往往比不使用DI更糟糕。