2013-01-15 32 views
0

我越來越發現自己混合運行時參數和隱式構造注入,它對我來說味道不好。DI和運行時參數 - 結構圖

實施例 - I有一個基類描述過濾器,以及各種遺傳類型特定過濾器(標籤,類別,日期,作者,等等等等)

var filter = StructureMap.ObjectFactory 
.With("caption").EqualTo("Posts filtered by tag:") 
.With("parameters").EqualTo(parameters) 
.With("displayInSummary").EqualTo(true) 
.GetInstance<TagListFilter>(); 

我這樣做的原因是因爲在構造函數我使用,我希望StructureMap注入的具體類(IArticleConfigurator)的接口:

public TagListFilter(string caption, IDictionary<string,string> parameters, bool displayInSummary, IArticleConfigurator configurator) 
:base(caption, parameters,displayInSummary, configurator) 

,但它只是發生在我,我更換一個簡單的構造,儘管有一個具體的類,而不是接口,帶,本質上是一樣的但使用DI注入1個混凝土類型。我這樣做是因爲目前我們的配置是在一個xml文件中,但會被移動到一個CMS,所以使用接口似乎是一個好主意。

這似乎是錯誤的,不在DI的精神。

我應該使用工廠來生成我的各種過濾器嗎?如果是這樣,我還可以利用DI來獲得我的IArticleConfigurator的具體實例嗎?

回答

1

您不應該將參數從一個依賴顯式地傳遞給另一個,或者至少應該儘量減少它們的數量。使用參數解析實例的一個主要缺點是,您將參數名稱指定爲字符串文字 - 這會使您在構造函數簽名更改時非常脆弱。

我可能會想到的一個例子(請注意,我不知道您的域和實體的責任)是注入提供者還是像您之前所說的那樣是工廠。例如,創建類似ITagListFilterConfigurationProvider(你應該改變你的名字,我只是想提供動力)。您可以創建非常抽象的提供商像IFilterConfigurationProvider有三種方法如下,如果你有一個過濾器相同的參數:

interface ITagListFilterConfigurationProvider 
{ 
    string Caption { get; } 
    IDictionary<string,string> GetParameters(); 
    bool IsDisplayInSummary { get; } 
} 

現在你構造的樣子:

public TagListFilter(ITagListFilterConfigurationProvider configurationProvider, IArticleConfigurator configurator) 

所有你需要的是實現它就像你已經做過的那樣(因爲你正將具體參數傳遞給構造函數)並將這種行爲提取給提供者。而剩下的 - 是沒有經過任何具體的參數

var filter = StructureMap.ObjectFactory.GetInstance<TagListFilter>(); 
+0

我總是毫不猶豫地把屬性(例如,不中的方法做的東西),在接口方面採用StructureMap登記的具體提供者和解決過濾器,但我現在看到這個經常讓我認爲我現在會更頻繁地這樣做。 這種方法效果很好,非常感謝你,伊利亞。 –

+0

作爲後續工作 - 我將在使用繼承結構時使用Aggregator服務來減少我的構造函數接口參數。請參閱blog.ploeh.dk/2010/02/02/RefactoringToAggregateServices.aspx –