2010-08-26 78 views
2

当我们使用依赖注入容器时,理想情况下,我们只从其中抽取一个顶级对象(例如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

+1“Bazinga!” – 2010-08-26 18:51:37

+0

这是你的实际问题还是只是一个人为的例子? – 2010-08-26 19:34:21

+0

@Mauricio:我的实际问题稍微复杂一些:我有两个预先存在的类,它们彼此不知道,我希望第一个类上的事件触发第二个类上的方法调用。添加导入其他两个实例的第三个类似乎是实现这一目标的自然方式,但第三个类从未由依赖注入容器实例化。 – 2010-08-27 12:52:13

回答

0

A 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(); 
} 
5

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

我不认为这就是你的真正意思,所以你可以进一步解释你目前如何使用BazingaConsoleLogger?如果你实际上是使用BazingaConsoleLogger,你已经有一个依赖项(显式或不显式)给BazingaConsoleLogger。

编辑:为了使事件松散,我使用Windsor's Event Wiring facility。如果你的容器没有这样的东西,它应该不难编码,here are the general principles

+0

预期的效果是让控制台输出显示Bazinga事件。在我的例子中,只需创建'BazingaConsoleLogger'即可实现这种理想效果。但是,由于没有其他类使用BazingaConsoleLogger作为依赖项,因此依赖注入容器将永远不会创建它。换句话说,'BazingaConsoleLogger'实例的存在是组合的一个理想特性,但这不会遵循依赖关系自动执行。 – 2010-08-27 12:57:27

+0

@Wim Coenen:编辑我的回答WRT事件。 – 2010-08-27 13:22:16

3

在温莎,你可以破解这样的事情:

container.Register(
    Component.For<Notifier>() 
     .OnCreate((kernel, notifier) => 
     notifier.Bazinga += kernel.Resolve<BazingaConsoleLogger>().HandleBazinga) 
); 

但是我有毛里西奥·雅伯同意,我会将此视为气味,重新审视自己的设计,在这种情况下。