2016-04-14 61 views
2

我正在編寫一個應用程序(通過ASP.NET Web API公開),它的目的是消耗兩個數據源,並揭示相似之處和差異。所以API具有以下設置:簡單的噴油器依賴於兩個實現相同接口的對象

public class FooController : WebAPI 
{ 
    public FooController(IFooRepository repoFromSourceA, IFooRepository repoFromSourceB) 
    { 
     ... 
    } 
} 

維持其中之一是其源(SourceA和SourceB不能互換)似乎讓container.RegisterCollection(..)不可能(或非常危險的)使用的區別。此外,由於一個類正在使用這兩種實現,裝飾者似乎不適合。

那麼,我會如何設置這個依賴注入?

+0

在任何人能夠回答這個問題之前,最重要的問題是當兩個參數(意外)交換時'FooController'會發生什麼。因此,如果我們實例化新的FooController(新的RepoB(),新的RepoA())(它會編譯),'FooController'仍然會正常工作或者會中斷嗎? – Steven

+0

它不會中斷(不會拋出任何異常),但是API會對調用者說謊。一些電話的格式是「給我存在於A中但不在B中的物品」。如果它們被交換,呼叫者將獲得物品(或沒有物品),但結果將是錯誤的。 –

回答

6

你有一個很常見的問題。許多開發人員在開始使用依賴注入時都會遇到這個問題。處理這個問題時,找出您是否違反了Liskov Substitution Principle(LSP)總是很重要的,因爲當您這樣做時,您應該使用兩個單獨的接口。永遠不要忘記:接口不僅僅是方法簽名。它是合同執行情況如何表現以及他們返回的合同。

你的評論似乎表明你沒有違反LSP,因爲他們的行爲是相同的,他們可以相互交換(它可能會破壞應用程序,但不會破壞消費者)。

在Simple Injector中處理此問題的方法是使用context based injection使用RegisterConditional方法。例如:

container.RegisterConditional<IFooRepository, FooRepoA>(
    c => c.Consumer.Target.Parameter.Name.Contains("SourceA")); 
container.RegisterConditional<IFooRepository, FooRepoB>(
    c => c.Consumer.Target.Parameter.Name.Contains("SourceB")); 

這裏RegisterConditional方法與斷言,消費者在依賴注入,構造函數的參數都有一個包含任何「SourceA」或「SourceB」的名稱提供。

+0

完美;這看起來正是我想要的。是的,我有點害怕違反LSP,所以這是我多次檢查之前尋求幫助。 –

相關問題