依赖注入容器:如何处理不依赖于任何东西的对象?

时间:2010-08-26 17:28:06

标签: c# dependency-injection

当我们使用依赖注入容器时,理想情况下我们只从中提取单顶级对象(例如Program的实例),并让容器自动组合应用程序的其余部分。

但是,有时候有些对象不是其他任何东西的依赖,但我们希望将它们放在对象图中。例如,我可以拥有一个Notifier类,其中包含Bazinga个事件,以及此BazingaConsoleLogger类:

public class BazingaConsoleLogger
{
    private readonly Notifier notifier;

    public BazingaConsoleLogger(Notifier notifier)
    {
        this.notifier = notifier;
        this.notifier.Bazinga += HandleBazinga;
    }

    private void HandleBazinga(object sender, EventArgs args)
    {
        Console.WriteLine("Bazinga!");
    }
}

因为BazingaConsoleLogger不是任何依赖项,所以它不会由依赖项注入容器创建。解决这个问题的最佳方法是什么?

3 个答案:

答案 0 :(得分:5)

如果BazingaConsoleLogger是一个服务而不是任何依赖项,那么它不会在程序中的任何地方使用,因此可以删除该类。更少的代码FTW! : - )

我认为这不是你的意思,所以你能否进一步解释你目前如何使用BazingaConsoleLogger?如果 实际上正在使用BazingaConsoleLogger,那么您已经对BazingaConsoleLogger具有依赖关系(显式与否)。

编辑:松散地连接事件我使用Windsor's Event Wiring facility。如果您的容器没有类似的东西,那么编写代码并不困难,here are the general principles

答案 1 :(得分:3)

在温莎你可能会破解这样的事情:

container.Register(
   Component.For<Notifier>()
      .OnCreate((kernel, notifier) => 
         notifier.Bazinga += kernel.Resolve<BazingaConsoleLogger>().HandleBazinga)
);
然而,我同意Mauricio Scheffer的观点,我认为这是气味并在这种情况下重新考虑你的设计。

答案 2 :(得分:0)

可以将IListener标记接口添加到类中。在应用程序启动代码中,除了主程序实例之外,我还可以从容器中提取所有IListener个实例:

container.Resolve<IEnumerable<IListener>>(); // just to create the listeners
var program = container.Resolve<Program>();
program.Run();

另一种选择是使用IStartable接口(inspired by Autofac)来解决更普遍的问题,即在启动时启动多个服务。对于事件侦听器类,Start方法可用于订阅事件(从而从构造函数中删除此责任)或者根本不执行任何操作。 Program类可以是IStartable实现之一。

var startables = container.Resolve<IEnumerable<IStartable>>();
foreach (var startable in startables)
{
    startable.Start();
}