4

私は依存性注入を学び始めたばかりで、ここで立ち往生しています。

私のプロジェクトには、Entity Framework DbContext を介した WCF DataService があります。

public class MyDataService : DataService<MyDbContext>
{

    protected override MyDbContext CreateDataSource()
    {
        // I want to use dependency injection for this
        return new MyDbContext();
    }
}

このクラスは、
a) IIS でホストされているため、制御できない b) で作成された統合テスト用var host = new DataServiceHost(type, new Uri[] { });

どちらも MyDbContext に異なるコンストラクターを使用します

したがって、基本的にこれでコンテキストを注入するには

    protected override MyDbContext CreateDataSource()
    {
        INinjectModule module = ???; // - 
        IKernel kernel = new StandardKernel(module);
        return kernel.Get<MyDbContext>();
    }

問題は、この状況でのベスト プラクティスは何かということです。するべきか:

a) メイン プロジェクトとサービスの両方が使用するクラス ライブラリにモジュールを作成します。b) Ninject モジュールを保持する DataService プロジェクト内に public static 変数を作成します。c) Ninject カーネルを保持する DataService プロジェクト内に public static 変数を作成します d) 他の何か。

私は次のようなものを好むだろう

    protected override MyDbContext CreateDataSource()
    {
        DefaultKernel.Get<MyDbContext>();
    }
4

1 に答える 1

3

まず、コンポジション ルートが必要です。つまり、あなたが作成される単一の場所Kernelです(すべての機能ではありません)。

第二に、ここは必要ありませんNinjectModule..Ninjectに具体的なオブジェクトのインスタンスを作成するように依頼しています(ほとんどすべての状況で..目的を無効にします)。

作成する必要があるのは、 ..NinjectModuleのコンストラクターに別のパスを渡すことです。次のようなものです。Kernel

interface IContext {
}

class MyDbContext : DbContext, IContext {
}

class YourModule : NinjectModule {
    protected override void Bind() {
        Bind<IContext>().To<MyDbContext>();
    }
}

// In your composition root somewhere
var kernel = new StandardKernel(new NinjectModule[] { new YourModule() });

// in your createdatasource method
kernel.Get<IContext>();

これで始められます。通常、コンポジション ルートは、アプリケーション全体でオブジェクトのインジェクションを駆動するものであり、その結果、パスKernelアラウンドの必要がなくなります (現在のセットアップで行う必要があります)。

DI/IoC を使い始めるときに理解するのが難しいことは、依存関係グラフ全体を作成するのはコンテナーの仕事だということです。したがって、次のバインディングをセットアップする場合:

IContract1 -> ConcreteObject1
IContract2 -> ConcreteObject2
IContract3 -> ConcreteObject3

..次の設定があります。

class ConcreteObject1 : IContract1 {
    public ConcreteObject1(IContract2 contract3) {
    }
}

class ConcreteObject2 : IContract2 {
    public ConcreteObject2(IContract3 contract3) {
    }
}

コンテナにIContract1(これは になりますConcreteObject1) の具体的な実装を要求すると、それが作成されます.... しかし:コンストラクタでConcreteObject1の具体的な実装が必要IContract2です。したがって、コンテナは「待って、これを作成する方法を知っています」と言い、..のインスタンスを渡しますConcreteObject2。繰り返しますが、「待って、 ..ConcreteObject2の具体的な実装が必要IContract3です。もう一度、行ってフェッチします。

うまくいけば、それは役に立ちます。

于 2013-07-03T10:35:31.360 に答える