在不继承继承的情况下注入基本控制器的正确方法

时间:2019-05-20 17:05:53

标签: c# asp.net-core dependency-injection

我有一个像这样的控制器。

public SomeController : Controller
{
  private readonly InjectableIntoEveryController _thing;
  public SomeController(InjectableIntoEveryController thing, ...) { ... }
}

自然,我内部的开发人员希望将 InjectableIntoEveryController 事物移至基本控制器,并避免显式且可忽略的注入。因此,我正在创建以下内容。

public BaseController : Controller
{
  private readonly InjectableIntoEveryController _thing;
  public BaseController(InjectableIntoEveryController thing, ...) { ... }
}

public SomeController : BaseController
{
  public SomeController(...) { ... }
}

这不会编译,因为在基类中没有无参数的构造函数。但是,如果我们如下所示添加一个,则不会进行注入,这将无法达到目标。

public BaseController : Controller
{
  private readonly InjectableIntoEveryController _thing;
  public BaseController() { ... }
  public BaseController(InjectableIntoEveryController thing, ...) { ... }
}

我发现使其飞行的唯一方法是使用 base(...)调用传递事物,但这需要注入它,破坏了整个重构的目的。

public SomeController : BaseController
{
  public SomeController(InjectableIntoEveryController thing, ...)
  :base(thing) { ... }
}

有没有更好的方法来确保基本控制器按我的意愿注入东西,而不必从继承的东西中显式传递它们?

2 个答案:

答案 0 :(得分:3)

一种无需每次都指定每个依赖项的简单方法是将依赖项转储到容器类中,然后将那个注入到所有控制器中:

public class Dependencies : IDependencies
{
     public Dependencies(IDependency1 d1, IDependency2 d2, <etc>) 
     {
          this.d1 = d1;
          this.d2 = d2;
          <etc>...
     }
}

在您的控制器中,您现在可以简单地注入该类。

public SomeController 
{
     public SomeController(IDependencies d) { 
         this.d = d; 
     }
}

即使您必须添加/删除依赖关系,其签名也不会改变,因此所有控制器都可以访问其共享的依赖关系,而不必每次更改依赖关系时都需要修改其签名。

不过,我会同意以下意见:如果这是您所遇到的问题的解决方案,那么您可能想要检查为什么一个类具有如此多的依赖关系(或为什么这么多的类都具有相同的列表) 。不过,我绝对可以理解自己受到环境的限制(也就是说,我本人已经使用了此解决方案)!

答案 1 :(得分:1)

我今天遇到了同样的问题,并且阅读了这个问题。接受的解决方案不能满足我的需求,因为没有BaseController进行注入。这是一个解决方案,可让您直接注入BaseController类,避免构造函数注入及其继承的所有缺点:

    public class BaseController : Controller
    {
        private InjectableIntoEveryController _thing;
        public InjectableIntoEveryController Thing
        {
            get
            {
                if (_thing == null && HttpContext != null)
                    _thing = (InjectableIntoEveryController)HttpContext.RequestServices.GetService(typeof(InjectableIntoEveryController));
                return _thing;
            }
        }
    }