25

私はついに依存性注入に足を踏み入れています(長い間遅れていました)。Unity を使い始めて、戦略パターンの問題に遭遇しました。コンテナーを使用して、名前に基づいて戦略の特定の実装を返すことができますが、コンテキストで適切な戦略を取得する方法がわかりません。
簡単な例で説明しましょう。コンテキストは車で、IEngine (戦略) があり、FastEngine と SlowEngine の 2 つの実装があります。コードは次の行に沿って表示されます。

public interface IEngine
{
    double MaxSpeed
    {
        get;
    }
}

internal class FastEngine:IEngine
{
    public double MaxSpeed
    {
        get 
        { 
            return 100d; 
        }
    }
}

internal class SlowEngine:IEngine
{
    public double MaxSpeed
    {
        get
        {
            return 10d;
        }
    }
}

public class Car
{
    private IEngine engine;
    public double MaximumSpeed
    {
        get
        {
            return this.engine.MaxSpeed;
        }
    }

    public Car(IEngine engine)
    {
        this.engine = engine;
    }
}

私の問題は次のとおりです。速い車または遅い車をインスタンス化するにはどうすればよいですか? コンテナを使用して各実装を提供し、使用する「デフォルト」実装を設定できます。

IUnityContainer container = new UnityContainer();
container.RegisterType<IEngine, FastEngine>();
container.RegisterType<IEngine, FastEngine>("Fast");
container.RegisterType<IEngine, SlowEngine>( "Slow" );
var car = container.Resolve<Car>();
Assert.AreEqual(100, car.MaximumSpeed);

しかし、私が望むのは、戦略の特定の実装を備えた車をリクエストできることです-次のようなものです

var car = container.Resolve<Car>(??? use "Fast" or "Slow ???);

コンテナを使用してそれを行うことはできますか? または、コンテナーを使用する Factory を作成する必要がありますか? 任意のガイダンスをいただければ幸いです-これについて正しく考えているかどうかはわかりません!

4

1 に答える 1

28

DI の一般的なパターンは、実行時に特定の抽象化の単一の実装しかないというものです。あなたが説明したような曖昧さに対処する必要がないので、それは人生をずっと楽にします.

ただし、例のように、コンテキストに基づいて実装を変更する必要がある場合があります。多くの DI コンテナーは、修飾パラメーターを提供できる方法を提供しますが、これは、コードを特定の DI コンテナーに密結合することになることを意味します。

より良い解決策は、必要なものを提供できるAbstract Factoryを導入することです。何かのようなもの

public interface ICarFactory
{
    Car Create(IEngine engine);
}

より多くの戦略を挿入する必要がある場合は、おそらくBuilder設計パターンがさらに適している可能性があります。

いずれにせよ、要点は、コンテナーに多数の異なる Car を登録する代わりに、単一の ICarFactory 実装を登録することです。

クライアント コードでは、注入された ICarFactory を使用して、特定の IEngine に基づいて Car インスタンスを作成します。

var car = factory.Create(engine);
于 2009-11-10T08:22:13.167 に答える