NuGetのNinject3.0.1.10とninject.extensions.factory3.0.1.0を使用しています-「実際の」シナリオでは、(手動でIFooをバインドするのではなく)ninject.extensions.conventionsも使用しますが、質問を単純化するために、これを避けてください。
私はIFooインターフェースとその複数の実装を持っており、それぞれがGen1とGen2と呼ばれる子名前空間とサブフォルダーの下にあります。指定されたパラメーター(文字列、列挙型など)に基づいてIFooを返すことを目的としたIFooFactoryインターフェイスがあります。
この例では、列挙型を使用してわかりやすくしています。最初は文字列バージョンを作成しましたが、文字列などのより任意のパラメーターを渡すことに対する反対意見は、問題を混乱させるだけだと感じました。
public enum ImplementationGeneration
{
Gen1,
Gen2,
Gen3,
}
public interface IFoo
{
void DoStuff();
}
public interface IFooFactory
{
IFoo CreateFoo(ImplementationGeneration implementationGeneration);
}
namespace SomeRootNamespace.Gen1
{
public class Foo : IFoo
{
public void DoStuff()
{
Console.WriteLine("Doing Type1 stuff");
}
}
}
namespace SomeRootNamespace.Gen2
{
public class Foo : IFoo
{
public void DoStuff()
{
Console.WriteLine("Doing Type2 stuff");
}
}
}
さて、このような実装をコンシューマーに「選択」させることは、理想的には存在しないカップリングの形式であることを理解していますが、私見では、Ninjectがすでにサポートしている名前付きバインディングと同じレベルのカップリングです。実装に属性を追加することは避けたかったのですが、GetGen1 / GetGen2 / etcメソッドをファクトリインターフェイスに含めることは、これに非常に適しています。呼び出し先のメソッドに入力をマップするために、どこかのスイッチを介してOCPに違反することになります。 (または手動でリフレクションを使用)
可能であれば避けたいと思っている完全な/動作するコードはここにあります:https ://gist.github.com/4549677
2つのアプローチを使用します。
- 列挙型のスイッチが渡されたOCPに違反する手動のファクトリ実装
- IInstanceProviderのインスタンスでファクトリ拡張を使用します(GetInstanceをオーバーライドするためにStandardInstanceProviderをサブクラス化します)。
2番目のアプローチは、これを機能させるために「正しい方法」に「近い」可能性があるように見えますが、1)作業を行うためにカーネルへの参照を保持します。これはおそらく悪い考えであり、2)呼び出し中にすべてのIFooバインディングを検索したときに、IFooのバインディングに具体的なタイプが見つかりませんでした。現在、GetAllを実行しているため、このシナリオに必要な数よりもN-1多いインスタンスをインスタンス化します。