2

2つのデータソースを消費し、類似点と相違点を明らかにするアプリケーション(ASP.NET Web API経由で公開)を作成しています。同じインタフェースを実装する2つのオブジェクトに依存する単純なインジェクタ

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

1は、(SourceAとSourceBを交換することはできません)container.RegisterCollection(..)が不可能(または非常に危険)を使用して作るように思われたソースであることの区別を維持:だからAPIは次のセットアップを持っています。さらに、1つのクラスが両方の実装を消費しているため、Decoratorは適合していないようです。

どうすればこの依存性注入を設定できますか?

+0

誰かがこの質問に答える前に最も重要な質問は、2つの引数が(誤って)交換されたときに 'FooController'がどうなるかということです。したがって、新しいFooController(新しいRepoB()、新しいRepoA()) '(コンパイルする)をインスタンス化すると' FooController'は正しく機能しますか、それともブレークしますか(例えば例外がスローされます)? – Steven

+0

例外は発生しませんが、APIは呼び出し側にあります。コールの中には、「Aには存在しBには存在しないアイテムを私に渡す」形式のものがあります。スワップされていれば、呼び出し元は項目を戻すことになりますが、結果は誤っています。 –

答えて

6

ご質問は非常に一般的です。 Dependency Injectionで始める場合、多くの開発者がこれに苦労しています。これに対処するときは、Liskov Substitution Principle(LSP)に違反しているかどうかを調べることが常に重要です。なぜなら、そうするときは、2つの別々のインターフェイスを使用する必要があるからです。決して忘れないでください:インターフェイスは単なるメソッドシグネチャ以上のものです。これは、その契約の実装がどのように動作し、返品するかの契約です。

あなたのコメントは、LSPに違反していないことを示しています。その動作は同じであり、相互に交換することができます(アプリケーションが壊れても消費者を壊すことはありません)。

Simple Injectorでこれを処理するには、RegisterConditionalメソッドを使用してcontext based injectionを使用します。例えば:

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に違反することについて少し怖いので、私は何度も何度もチェックして助けを求めます。 –

関連する問題