当我们使用依赖注入容器时,理想情况下我们只从中提取单顶级对象(例如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
不是任何依赖项,所以它不会由依赖项注入容器创建。解决这个问题的最佳方法是什么?
答案 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();
}