3

以下の簡略化された例では、かなり合理的な方法で定義されていると思うDataContextとリポジトリがあります。

public interface IUnitOfWork 
{
   int SaveChanges();
}

public class DataContext : DbContext, IUnitOfWork 
{
    public DbSet<Car> Cars { get ; set; }
}

public interface ICarsRepository 
{
    Car Find(int id);
    void Add(Car car);
}

public class SqlCarsRepository : ICarsRepository 
{
    private DataContext  _context;
    public SqlCarsRepository(DataContext context)
    {
       _context = context;
    }

    public Car Find(int id) 
    {
        return _context.Cars.Find(id);
    }

    //etc
}

DIと抽象的なファクトリパターンを使用して、自分が望むものを実現する方法を見つけるのに苦労しています。MVCアプリケーションでは、これは簡単にセットアップできます。コントローラーは、コンストラクターにIUnitOfWorkとICarsRepositoryの実装のインスタンスを必要とします。別のコントローラーファクトリを使用して、Httpリクエストごとに同じDataContextインスタンスを提供するようにコンテナーを構成できます。どういうわけか、ここでは使い捨ての依存関係が正しく処理されているようです。

ただし、Windowsサービス内で同じリポジトリを使用したいと思います。これはマルチスレッドであり、開始時に各スレッドは独自のリポジトリにアクセスする必要があり、各スレッドは独自のDataContext/UnitOfWorkを持つ必要があります。しかし、私はこれを行う方法がわかりません:

  • アプリケーションの複合ルートはサービスの開始時であるため、スレッドごとに依存関係を解決することはできません(スレッドはオンデマンドで開始されます)。
  • 抽象ファクトリパターンをどのように使用できるかわかりません。スレッドにはIUnitOfWorkとICarsRepositoryのインスタンスが必要ですが、同じDataContextを共有しています。抽象ファクトリを作成して、これらの両方を1回の呼び出しで作成し、それをスレッドに渡すことはできますが、DataContextを破棄する方法がわかりません。ICarsRepositoryの実装への依存関係が使い捨てであることをスレッドが気にする必要はありません。ICarsRepositoryがDataContextに依存していることをスレッドに知られたくないのは、インターフェイスが無意味に見えるためです。スレッドはSqlCarsRespositoryに依存している可能性があります。
  • DataContextを使用している他の人がいる可能性があり、そもそもそれを作成しなかったため、SqlCarsRepositoryを使い捨てにしてDataContextを破棄させたくありません。
  • IUnitOfWorkとICarsRepositoryを非表示にするCarsServiceを作成できると思いました(そして抽象ファクトリを使用してそのインスタンスを取得します)が、それでもDataContext依存関係を破棄する方法がわかりません

私が試みていることを行うための最良の方法は何ですか?

4

1 に答える 1

2

そのため、スレッドごとに依存関係を解決することはできません

彼らはできるし、実際そうすべきだ。各スレッドの開始時に、新しいオブジェクト グラフを解決する必要があります。これを行わないということは、スレッドセーフな依存関係しか使用できないことを意味しますが、これはあなたの状況には当てはまりません。

抽象ファクトリ パターンの使用方法がわかりません

DataContext最初は、MVC アプリケーションでは Per Web Request として定義し、Windows サービスでは Per Lifetime Scope (または使用するコンテナーで利用可能なもの) として定義してみてください。Windows サービスでは、各スレッドが独自のライフタイム スコープを取得します。スコープを定義すると、多くの場合、スコープの終了時にインスタンスを破棄できます。

ICarsRepository の実装への依存関係が使い捨てであることをスレッドが気にする必要はありません。

スレッドはこれを気にする必要がありますが、ビジネス ロジックは気にする必要はありません。新しいスレッドを開始するときは、スコープの開始と終了、およびグラフのルート タイプの解決と使用を可能にするインフラストラクチャ コードが必要になります。このコードはコンポジション ルートの一部である必要があるため、アプリケーションの残りの部分はこれに気付かないようにする必要があります。Per Lifetime Scope (またはその他の明示的な有効期間) を使用していくつかの型を登録した場合、コンテナーはインスタンスをいつ破棄するかを認識します。インフラストラクチャ コードは、スコープが終了したことをコンテナーに通知するだけです。

SqlCarsRepository を使い捨てにしたくない

は、 をSqlCarsRepository実装しないインターフェイスに依存する必要がIDisposableあり、その場合、破棄するものはありません。これは、 の廃棄を担当するコンテナである必要がありDataContext、適切な登録を行うことでこれを行うことができます。

私が試みていることを行うための最良の方法は何ですか?

あなたのデザインは合理的に聞こえますが、ここにいくつかの他の SO の質問があります。

于 2012-06-28T11:24:23.100 に答える