2010-08-26 79 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) 
); 

但是我有毛裏西奧·雅伯同意,我會將此視爲氣味,重新審視自己的設計,在這種情況下。