19

我在我的項目中有一個通用的存儲庫。 考慮以下控制器片斷ASP.NET核心中的通用存儲庫沒有Startup.cs中每個表單獨的AddScoped行?

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); 
    } 

我不認爲需要有兩個在我的通用庫我的數據庫參考,以及我的每一個控制器。

我把它重構爲:

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行代碼時,它看起來不正確。

感覺就像複製和粘貼代碼。每次我通過添加一個新的模型和控制器來添加一個新的表格時,我的代碼將被編譯而不會給我一個錯誤。但是,如果我運行該程序,並轉到這一觀點我能得到控制器運行錯誤,如果我忘了向AddScoped行添加到我的Startup.cs。不太適合可維護性。

我的問題:

  1. 是不是真的最好的做法有在Startup.csConfigureServices方法爲每一個services.AddScoped和每一個查找表?

  2. 它是一個通用的倉庫,所以不存在是寫在一行中的100條複製和粘貼線的方法嗎?

  3. 如果沒有,那麼什麼是最好的實踐方式來做到這一點使用我的代碼?

+0

您使用Lookup1Controller'的'構造器'IGenericRepository '*爲參數*:'公共Lookup1Controller(IGenericRepository 庫)'。因此你期望* MVC用相應的參數調用控制器構造函數'Lookup1Controller'。誰應該使新的GenericRepository >()'?是否應該一次或每次調用'Index'操作?因此,您可以在「services.AddTransient」,「services.AddScoped」,「services.AddSingleton」和「services.AddInstance」之間進行選擇。 – Oleg

+0

這是一個基本的CRUD系統。所以有Create。更新,刪除方法我省略了。使用AddScoped似乎是執行此操作的標準方式請參閱:http://wildermuth.com/2015/3/17/A_Look_at_ASP_NET_5_Part_3_-_EF7。如果有更好的方式,請分享。 – devc2

回答

39

只需使用非通用註冊重載然後同時提供您的界面open generic types和執行(你需要通過2個Type對象的人。):

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

在你控制器添加特定類型的倉庫的依賴(封閉泛型類型)

public HomeController(IGenericRepository<Lookup1> repository) 
{ 
    ... 
} 
+0

謝謝。改變一行代碼的作品。將等待看看其他人是否提供輸入,如果這是一個良好的做法或不是爲一個ASP.net 5應用程序或提供alterantives – devc2

+0

他們註冊的方式是相同的其他DI容器,如[Ninject](http://stackoverflow.com/a/10243699/1836935)或[Unity](https://msdn.microsoft.com/en-us/library/ff660936(v = pandp.20).aspx#Anchor_0)。讓我們來看看是否有人知道ASP中的內置容器有什麼問題.Net 5 –

+3

這不適用於我。我得到這個錯誤:失敗:Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware [0]發生未處理的異常:嘗試激活'SqlExpress.Helpers.LessonTagHelper'時無法解析類型爲'SqlExpress.Repository.Interfaces.IChatRepository'的服務。 System.InvalidOperationException:嘗試激活「SqlExpress.Helpers.LessonTagHelper」時無法解析類型爲「SqlExpress.Repository.Interfaces.IChatRepository」的服務。在... – Beetlejuice

相關問題