如何在不更改子控制器的情况下创建一个接受控制器参数的基础class?

How to create a base class that accepts parameters for controllers without changing child controllers?

我正在尝试将 ninject 添加到以下设置 -

public class BaseController : Controller
{
    protected ILogger Logger {get;}
    public BaseController() { Logger = new MyLogger(); }
}
public class Controller1Controller : BaseController { ... }
public class Controller2Controller : BaseController { ... }
....
public class ControllerNController : BaseController { ... }

使用 ninject,将 ILogger 参数添加到 BaseController 效果很好 -

public class BaseController : Controller
{
    protected ILogger Logger {get;}
    public BaseController(ILogger logger) { Logger = logger; }
}

但现在它还需要在每个子控制器中添加一个构造函数,因为基础 class 不再具有无参数构造函数-

public class Controller1Controller : BaseController { 
    public Controller1Controller(ILogger logger) : base(logger) { }
}

有超过 50 个子控制器,如果我们必须 add/remove 更多的依赖关系,那么它可能会成为一个维护问题。此外,添加到每个控制器的代码完全相同。

有没有办法让子控制器保持原样(没有任何构造函数)但仍然对 BaseController 进行更改?

简单回答:否(您必须更新派生的 class 构造函数)

说明:要在派生和基础 classes 之间传递 ILogger 的注入实例,您需要使用 ILogger 参数更新派生构造函数,然后将参数转发给基础。除非,对于这种情况有更明智的解决办法。

参见 wiki 缺点部分的第一点 DI Disadvantages(DI自带行李)

另外:您可以在基 class 中创建一个受保护的成员来保存 ILogger 实例,这将使所有派生的 classes 都可以访问这个受保护的实例。

更新:部分同意tomludd使用属性注入的解决方案。参见 this SO answer。 有关更多 DI 技术,请阅读 Mark Seemann or his book DI in .NET

中的 articles/blogs

在 BaseController 构造函数中试试这个

public BaseController(ILogger logger = null) 
{ 
    if (logger != null)
        Logger = logger;
    else
        Logger = new MyLogger();
}

抱歉,没有。

作为替代解决方案,您可以从 Ninject 获取 ILogger:Using property injection instead of constructor injection