2017-11-13 18 views
1

DbContextの実装に複数の接続文字列があるアプリケーションがあります。このクラスを消費するクラスでサポートするために、私は、を実装するGetメソッドを使用して、DbContextのインスタンスを提供するIDbContextProviderインターフェイスを作成しました。シンプルなインジェクタデコレータと共分散

私もICommandHandlerのことが起こっています。コマンド実行に成功するとDbContext.SaveChangesAsync()というデコレータを作成しようとしています。私はDbContext実装における型パラメータを追加したくない、と私はDbContextから派生したすべてのクラスがSaveChangesAsync()方法を知っているので、私は、私を考え出し、今

container.RegisterDecorator(typeof(ICommandHandler<>), 
    typeof(SaveChangesCommandHandlerDecorator<>)); 

:私はこのように私のデコレータを登録しています共分散を使用することができます。だから私のインターフェースは次のようになります。

public public interface IDbContextProvider<out TDbContext> where TDbContext : DbContext 
{ 
    TDbContext Get(DbPrivileges privileges); 
} 

そして、私のデコレータの関連部分:しかし

public class SaveChangesCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand> 
    where TCommand : ICommand 
{ 
    private readonly ICommandHandler<TCommand> _handler; 
    private readonly IDbContextProvider<DbContext> _dbContextProvider; 

    public SaveChangesCommandHandlerDecorator(
     ICommandHandler<TCommand> handler, IDbContextProvider<DbContext> dbContextProvider) 
    { 
     _handler = handler; 
     _dbContextProvider = dbContextProvider; 
    } 

    ... 

、私は私のコンテナにVerify()を呼び出し、それは見ているようIDbContextProviderは、無効であることを訴えます私のアプリに登録されているものの代わりに "ベース" IDbContextProvider<DbContext>のために。

タイプのコンストラクタSaveChangesCommandHandlerDecorator < CreateUserCommand>名前のパラメータが含まれている 'dbContextProvider' とIDbContextProvider < DbContextを入力> registered.Please IDbContextProvider < DbContext>確実ではないことは、登録、またはSaveChangesCommandHandlerDecorator < CreateUserCommandのコンストラクタを変更しています>。要求された型が(Redacted).IDbContextProvider < Microsoft.EntityFrameworkCore.DbContext>の間に、別の型(Redacted).IDbContextProvider < TDbContextの登録が存在することに注意してください。

Simple Injectorは、dbContextProviderパラメータに注入する具体的なタイプを知る方法がないため、実際には意味があります。

デコレータが作成される方法をカスタマイズする方法はありますか。基礎となるICommandHandler実装の依存関係を調べてそこからIDbContextProvider署名を作成することができますか?だから私のコマンドハンドラがIDbContextProvider<AwesomeDbContext>なら、私はそれを私のデコレータでも解決したいと思っています。

答えて

2

だから、私はまっすぐに、これを取得してみましょう:

  • AwesomeDbContext
  • EventBetterDbContext
  • BrilliantDbContext

今、各コマンドハンドラは、一般的に依存します:アプリケーションは、次のような複数のDbContext implemtantationsは、含まれています1つの特定のDbContext実装では、IDbContextProvider<TDbContext>を取得することによって、TDbContextは具体的なDbContextの実装です。

デコレータのコマンドハンドラが依存しているものによっては、まったく同じIDbContextProvider<TDbContext>の実装をデコレータに注入したいので、その特定のインスタンスの変更を保存することができます。

あなたの質問を正確に要約すると、あなたの質問への短い答えは:いいえ、あなたはそれを行うことはできません。

長い答えはイエス、これはあなたのSaveChangesCommandHandlerDecorator<TCommand, TDbContext>デコレータにTDbContextための余分なジェネリック型引数を追加することで、実際に可能であり、Func<DecoratorPredicateContext, Type>を受け入れRegisterDecoratorオーバーロードを使用し、です。工場出荷時のデリゲートへの供給DecoratorPredicateContextを使用して、注入され、その情報に基づいているIDbContextProvider<TDbContext>あなたがTDbContextで埋めるだけに単純なインジェクタのためのオープンTCommandを残すSaveChangesCommandHandlerDecorator<TCommand, TDbContext>の部分的に閉じたバージョンをビルド見つけるためにそのExpression性質を分析することができます記入してください。

しかし、正直言って、私はこのルートを取っていません。それは多くの作業を必要とし、コードを理解するのが難しくなり、同僚があなたを憎むでしょう。

代わりにIDbContextProvider<TDbContext>インスタンスのリストをデコレータに挿入してみてください。 IDbContextProvider<out TDbContext>の登録を別々に、またはRegisterCollectionを使用してコレクションの一部として行うことで、これを行うことができます。

コレクションを挿入すると、デコレータは単にすべてのDbContextインスタンスで変更の保存を呼び出すことができます。 SaveChangesは、変更がない場合は本当に高速になるので、パフォーマンスの観点から、私は心配するものはないと思います。

+0

これは私の質問を正しく要約し、詳細な答えをありがとう!私は収集ルートを考慮しませんでしたが、間違いなくよりきれいなコードを生成するので、私はそれに行きます。 –