2

こんにちは私はMVC3アプリでNinject.MVCNugetパッケージを使用しており、コンストラクターインジェクション用に現在のバインディングを設定しています。

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IUnitOfWork>().To<ERSUnitOfWork>();
        kernel.Bind<IRepository<Recipe>>().To<GenericRepository<Recipe>>();
    }

私のコントローラーの例は以下のとおりです。

public class RecipesController : Controller
{
    private readonly IUnitOfWork unitOfWork;
    private readonly ERSDbContext context;
    private readonly IRepository<Recipe> recipeRepository;

    public RecipesController(IUnitOfWork unitOfWork, IRepository<Recipe> recipeRepository)
    {
        this.context = new ERSDbContext();
        this.unitOfWork = unitOfWork;
        this.recipeRepository = recipeRepository;
    }
}

コントローラーからプライベートDBContextプロパティを削除し、Ninjectが実行しているコンストラクターインジェクションの一部として新しいERSDbContext()をERSUnitOfWorkとGenericRepositoryのコンストラクターに渡したいのですが、できればコントローラー内でERSDbContextクラスの初期化を維持しますか?

これを行う方法についての助けをいただければ幸いです。ありがとう

NinjectWebCommonクラスでDbContextを作成する必要がないことを期待しています。これは、コントローラーで初期化する必要があります。

4

3 に答える 3

3

これは、依存関係をどのように抽象化するかという問題です。

インスタンスを作成するタイミングを制御したいので、次のように、タイプ固有のインスタンスDbContextを作成するファクトリが必要です。DbContext

public interface IDbContextFactory
{
     T CreateDbContext<T>() where T : DbContext;
}

(DIフレームワークがジェネリックインターフェイスの型パラメーターをかなりうまく処理する場合は、Entity Framework 5で導入されたIDbContextFactoryインターフェイスを使用できることに注意してください)

デフォルトのパラメーターなしのコンストラクターを使用して型付きインスタンスを作成するだけでよい場合はDbContext、次のようにインターフェースを定義できます。

public interface IDbContextFactory
{
     T CreateDbContext<T>() where T : DbContext, new();
}

そして、次のような実装を定義します。

public class DbContextFactory : IDbContextFactory
{

    #region Implementation of IDbContextFactory

    public T CreateDbContext<T>() where T : DbContext, new()
    {
        // Create a new instance of T and return.
        return new T();
    }

    #endregion
}

別のコンストラクターを呼び出す必要がある場合は、new()制約を削除し、リフレクション呼び出しを使用する必要があります(または、ラムダ式を作成し、のタイプに基づいてキャッシュすることができますTDbContext

そこから、他のインターフェースと同様に、IDbContextFactoryコントラクトを実装に関連付け、実装をクラスに注入します。IDbContextFactory

于 2012-09-16T23:07:46.687 に答える
1

これは、依存性注入の利点の1つであり、すべてのコンストラクターパラメーターとそれに依存するコンストラクターパラメーターを自動的に解決します。これはすべてあなたに代わって行われます。オブジェクトのマッピングを定義するだけです。

したがって、あなたの場合、あなたはこれを行うだけです:

kerel.Bind<ERSDbContext>().ToSelf();

次に、ERSDbContextをUoWとRepoに追加するだけで、問題ありません。

ユニットテストを行う場合は、casperOneで言及されているように、または私が言及したように(DbContextを汎用インターフェイスから派生させる場合)、コンテキストを何らかの方法で抽象化してから、代わりにこれを行う必要があります。

kernel.Bind<IDbContext>().To<ERSDbContext>();

DIを使用する利点の1つは、オブジェクトの存続期間を制御することです。DbContextの構築をDIコンテナの外部に延期する場合は、DIコンテナがライフタイムポリシーに基づいて管理できるようにするのではなく、手動でライフタイムを管理する必要があります(リクエストの終了時に自動的に破棄するなど)。

コンテキストの作成を遅らせることによる測定可能なメリットはありません。あなたは時期尚早の最適化をしていると思います。

于 2012-09-16T23:31:13.237 に答える
0

並行性の問題のため、当面はファクトリの使用を削除しましたが、時間が足りないため、このアプローチを使用しています。

kernel.Bind<ERSDbContext>().ToSelf().InRequestScope();

次に、私のUoWとGenericRepositoryで、コンストラクターはERSDbContextタイプのパラメーターを期待します。

後でこのアプローチを改善したいと思いますが、今のところこれは機能します。

于 2012-09-17T14:48:08.707 に答える