【问题标题】:Ninject: How to inject 'this' (the containing class) into an instance?Ninject:如何将“this”(包含类)注入实例?
【发布时间】:2017-02-06 13:27:49
【问题描述】:

总的来说,我是 Ninject 和 DI 的新手。

假设我有一个班级Caller

public class Caller : ICaller, ICallback {

  private ICommand command;

  public Caller(ICommand command) {
    this.command = command;
  }

  //callback method
  public void OnCommandCompleted() { }

}

Command 看起来像这样:

public class Command : ICommand {

  private ICallback Callback { get; set; }

  public Command(ICallback callback) {
    this.Callback = callback;
  }

  public void Execute() {

    //do something
    this.Callback.OnCommandCompleted();

  }

}

该命令应该具有对创建/注入它的类的引用。什么是合适的做法?当然,我可以从构造函数中删除依赖项,而是手动设置它:

public Caller(ICommand command) {
  command.Callback = this;
  this.command = command;
}

但是还有其他方法吗?

编辑:为了阐明我对这个设计的意图,我更新了给定的代码。 command 获得一个回调作为依赖项,在我的例子中是 Caller

【问题讨论】:

  • 为什么需要这个?这会导致循环依赖,这通常是一个坏主意,因为它们会增加复杂性。请更新您的答案,详细说明您为什么需要它并向您显示相关代码。通过这种方式,我们可以就如何修复您的设计向您提供反馈。
  • 嘿,实际上Command 需要一个ICallback 作为依赖项,以便在调用完成时通知调用者。我更新了我的示例代码以澄清这一点。

标签: dependency-injection ninject constructor-injection


【解决方案1】:

就像那样不容易。 也没有可以编写(替换容器)的 C# 代码来实现 ctor 注入场景:

new Caller(new Command(???))

==> 无法将 ??? 替换为对正在创建的 Caller 的引用,因为它尚未创建。

要实现循环引用,您必须执行以下操作:

var command = new Command();
var caller = new Caller(command);
command.InitializeWithCallback(caller);

所以我同意 Steven 的观点,这看起来很像糟糕的设计,应该重构,因此不需要循环依赖。此外,通常容器将不支持这种情况 - 在 ctor 时无法注入引用,因为尚未创建。

理论上,您可以通过将ICallback 代理注入Command 并在Caller 实例化后使用Caller 实例初始化代理来适应您的ctor 注入设计。但是,这引入了通常绝对没有根据的复杂性。归根结底,它只会使您的代码膨胀,而您也可以引入Command.InitializeWithCallback(caller)

【讨论】:

  • 我不认为这是一个糟糕的设计。实际上它是观察者模式。但是您是对的,如果没有 DI,我不会以这种方式实现它(正如您所指出的那样,这分别是不可能的)。我决定简单地使用Event 来达到我的目的。没有考虑到这种可能性,因为我是从 Java 移植结构。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多