web-dev-qa-db-ja.com

Startup.csのテーブルごとに個別のAddScoped行を持たないASP.NET Coreの汎用リポジトリ?

私のプロジェクトには一般的なリポジトリがあります。次のコントローラースニペットを検討してください

public class Lookup1Controller : Controller
{
    readonly MyDbContext _db;

    public Lookup1Controller(MyDbContext dataContext)
    {
        _db = dataContext;
    }

    public async Task<IActionResult> Index()
    {

        IGenericRepository<Lookup1> _repository = new GenericRepository<Lookup1>(_db);
        var lookup1s = await _repository.SelectAll();

        return  View(lookup1s);
    }

Genericレポジトリと各コントローラーの両方でデータベース参照を持つ必要はありません。

私はそれをリファクタリングします:

public class Lookup1Controller : Controller
{
    private IGenericRepository<Lookup1> _repository;

    public Lookup1Controller(IGenericRepository<Lookup1> repository)
    {
        _repository = repository;
    }

    public async Task<IActionResult> Index()
    {
        var lookup1s = await _repository.SelectAll();

        return  View(lookup1s);
    }

}

私が読んだことから、これは非常にすてきでASP.NET 5のベストプラクティスです。しかし、ブラウザでそのコントローラールートにアクセスすると、次のエラーが表示されます。

InvalidOperationException: Unable to resolve service for type 'MyProject.Data.IGenericRepository`1[MyProject.Models.Lookup1]' while attempting to activate 'MyProject.Controllers.Lookup1.

インターフェイスを使用するためにGenericRepositoryを挿入していないためです。

Startup.csAddScopedメソッドの各テーブルのConfigureServices行を追加します

services.AddScoped<IGenericRepository<Lookup1>,GenericRepository<Lookup1>> ();
services.AddScoped<IGenericRepository<Lookup2>,GenericRepository<Lookup2>> ();
services.AddScoped<IGenericRepository<Lookup3>,GenericRepository<Lookup3>> ();
services.AddScoped<IGenericRepository<Lookup4>,GenericRepository<Lookup4>> ();
etc

例外をスローせずにコードが実行されるようにします。

ただし、私のデータベースには約100個の単純なルックアップテーブルがあります。上記の100行のコードを見ると、正しく見えません。

コードをコピーして貼り付けるような感じです。ビューで新しいモデルとコントローラーを追加して新しいテーブルを追加するたびに、エラーが発生せずにコードがコンパイルされます。しかし、プログラムを実行してそのビューに移動すると、Startup.csにAddScoped行を追加するのを忘れた場合、コントローラーの実行エラーが発生する可能性があります。保守性にはあまり良くありません。

私の質問:

  1. Startup.csConfigureServicesメソッドのすべてのルックアップテーブルにservices.AddScopedを設定することは本当にベストプラクティスですか?

  2. これは汎用リポジトリなので、これらの100行を1行でコピーして貼り付ける方法はありませんか?

  3. そうでない場合、私のコードを使用してこれを行うためのベストプラクティスの方法は何ですか?

47
dfmetro

非ジェネリック登録オーバーロード(2つのTypeオブジェクトを渡す必要があるオーバーロード)を使用します。次に、インターフェイスと実装の両方の open generic types を指定します。

services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));

コントローラーで、特定のタイプ(閉じた汎用タイプ)のリポジトリーの依存関係を追加します

public HomeController(IGenericRepository<Lookup1> repository)
{
    ...
}
84
Daniel J.G.