5

私はSimple Injector IoCフレームワークを使用しており、実行時に依存関係の登録を変更したいと考えています。たとえば、ABという2つの実装があり、インタフェースはIです。実装Aはapp startに登録されていますが、実行時に変更される可能性のあるフラグによっては実装を切り替えたいと思います。私たちは現在、BaseControllerOnActionExecutingイベントを行っており、すべてのコントローラが継承しています。ここで私がしようとしているもののサンプルコードです。実行時に単純なインジェクタを使用して依存関係の登録を変更するにはどうすればよいですか?

protected override void OnActionExecuting(
    ActionExecutingContext filterContext) 
{ 
    if (IsRuntimeFlag) 
    { 
     // check current implementation type and 
     // change implementation to A 
    } 
    else 
    { 
     // check current implementation type and 
     // change implementation to B 
    } 

    base.OnActionExecuting(filterContext); 
} 

ご協力いただきありがとうございます。

if (IsRuntimeFlag) 
{ 
    container.Register<I, A>(); 
} 
else 
{ 
    container.Register<I, B>(); 
} 

又は均等の:場合IsRuntimeFlag

+1

これはDIコンテナを使用するのではなく、ファクトリを戦略パターンと組み合わせることをお勧めします。オブジェクトグラフを早期に解決するには、コンテナを使用します。 [Composition Root](http://blog.ploeh.dk/2011/07/28/CompositionRoot.aspx)を参照してください。 – TrueWill

+0

手動で行う必要がありますか? IOCコンテナフレームワークを使用するのはどうですか? –

答えて

9

が(したがって、アプリケーションの存続期間中に変更することはできません)設定値であり、次のように登録を行うことができ

container.Register(typeof(I), IsRuntimeFlag ? typeof(A) : typeof(B)); 

場合アプリケーションの存続期間中に値が変更され、適切なインスタンスへのディスパッチを扱うcompositeが適切な解決策になります。

複合体は、直接 ABに依存するため、以下のよう
public sealed class RuntimeFlagIComposite : I 
{ 
    private readonly A a; 
    private readonly B b; 

    public RuntimeFlagIComposite(A a, B b) { 
     this.a = a; 
     this.b = b; 
    } 

    void I.Method() => this.Instance.Method(); 

    private I Instance => IsRuntimeFlag ? this.a : this.b; 
} 

、あなたは単にそれを登録することができます

container.Register<I, RuntimeFlagIComposite>(); 

AまたはBは一時とは異なる寿命(要求ごとに新しいインスタンスを)持っている場合は、あなたをそれらを登録する必要があります。例えば:

container.Register<A>(Lifestyle.Singleton); 
container.Register<B>(Lifestyle.Scoped); 

また、あなたが複合ではなく、具体的なAB実装のI抽象化自体に依存させることができます:I抽象化によって

public class RuntimeFlagIComposite : I 
{ 
    private I a; 
    private I b; 

    public RuntimeFlagIComposite(I a, I b) 
    { 
     this.a = a; 
     this.b = b; 
    } 
} 

は、このクラスは、より柔軟かつよりますテスト可能。しかし、それを少し違うものに登録する必要があることを意味します:

container.Register<I, RuntimeFlagIComposite>(); 

container.RegisterConditional<I, A>(c => c.Consumer.Target.Name == "a"); 
container.RegisterConditional<I, B>(c => c.Consumer.Target.Name == "b"); 
+0

あなたの答えをありがとうが、このフラグはコンテナ登録時には不明であり、アプリケーションの存続期間を通して変更することができます。私はグローバルフラグを設定し、後でアプリケーションの中でそれを変更することができると思うが、私はそれがきれいなアプローチだとは思わない。よく見ると、私は複合パターンがこの場合にはうまくいくと思います。あなたの助けをもう一度ありがとう。 – Will

+0

こんにちはスティーブン、 あなたは他のアイデアがあるかどうかは不思議です。これを実装しようとすると、フラグは複合レイヤーがあるサービスレイヤーとは対照的に、Webアプリケーションレイヤー、クッキー値の中のものにも依存することに気付きました。したがって、コンポジットはフラグにアクセスできません。もう一度おねがいします。 – Will

+1

私はあなた自身の質問に答えたと思います。コンポジットがUI固有のものに依存する場合は、UIレイヤーで定義する必要があります。インターフェイスは下位レイヤーで定義されているので、UIレイヤーで定義することは絶対に賢明です(または、コンポジションルートの一部にすることもできます)。 – Steven

関連する問題