8

私はまだDIの初心者であり、物事を間違った方法で考えているかどうかを理解しようとしています. IRandomProvider に依存する Die オブジェクトを表現したいときに、おもちゃの問題に取り組んでいます。そのインターフェースは単純です。

public interface IRandomProvider 
{
   int GetRandom(int lower, int upper);
}

次のような Die コンストラクターが必要です。

Die(int numSides, IRandomProvider provider)

次のようなメソッドを持つ静的 DIFactory を使用しようとしています。

    public static T Resolve<T>()
    {
        if (kernel == null)
        {
            CreateKernel();
        }
        return kernel.Get<T>();
    }

ここで、CreateKernel は単に IRandomProvider の特定の実装にバインドします。

私はこれを呼び出すことができるようにしたい:

DIFactory.Resolve<Die>(20);

ConstructorArgs を処理できる特別なバージョンの "Resolve" を作成しないと、この作業を行うことはできません。それは物事を非常に複雑にしているようで、コンストラクターパラメーターの特定の名前に関連付けるだけでなく、その他のすべてのインスタンスに対して DIFactory を変更する必要があります。

int コンストラクターを使用しないように Die クラスをリファクタリングすると、すべて正常に動作します。しかし、クラスの要件であるため、numSides パラメーターを初期化することを覚えておく必要があります。

これは DI の悪いメンタル モデルだと思います。誰でも私を啓発できますか?

4

2 に答える 2

9

制御の反転は工場ではありません。Dieクラスのようなビジネスオブジェクトを解決するために使用しないでください。制御の反転は、コンテナがオブジェクトの存続期間を制御できるようにするために使用されるパターンです。そのボーナスは、依存性注入パターンもサポートしていることです。

ビジネスオブジェクトは通常、作成、変更、および破棄されます。したがって、それらのコンテナを使用する必要はありません。また、お気づきのとおり、コンストラクターで必須パラメーターを使用するため、コンテナーを使用するのが難しくなります。

DieFactoryコンテナにaを登録IRandomProviderし、コンストラクタでそれを取得させることができます。

public class DieFactory
{
    public DieFactory(IRandomProvider provider)
    {}

    public Die Create(int numberOfSides)
    {
        return new Die(numberOfSides, _provider);
    }
}

ただし、もちろん、関連するすべてのビジネスオブジェクトを作成するために使用されるファクトリを作成する方がよいでしょう。次に、カーネルを依存関係として使用できます。

public class AGoodNameFactory
{
    public DieFactory(IKernel kernel)
    {}

    public Die CreateDie(int numberOfSides)
    {
        var provider = _kernel.Resolve<IRandomProvider>();
        return new Die(numberOfSides, provider);
    }

    // other factories.
}

IRandomProviderまたは、クラスを作成するクラスの依存関係として直接取得することもできますDie

于 2012-08-27T06:22:53.843 に答える
5

この特定の状況では、ConstructorArgumentと一緒に使用できます。Kernel.Getここに完全なサンプルがあります。

モジュール構成

public class ExampleKernel : NinjectModule
{
    public override void Load()
    {
        Bind<IRandomProvider>()
            .To<RandomProvider>();

        Bind<Die>()
            .ToSelf()
            .WithConstructorArgument("numSides", 6);
                           //  default value for numSides
    }
}

コードで解決する

var d6 = kernel.Get<Die>(); // default numSides value
var d20 = kernel.Get<Die>(new ConstructorArgument("numSides", 20)); // custom numSides

Assert.That(d6.NumSides == 6);
Assert.That(d20.NumSides == 20);
于 2012-08-27T06:27:29.330 に答える