[英]No service for type 'MyType' has been registered
我有一個通用的存儲庫架構,如下所示:
資料庫
public interface IRepository<T> where T: class
{
IList<T> Get(Func<T, bool> where);
}
public abstract class Repository<T> : IRepository<T> where T: class
{
private readonly DbSet<T> _entity;
protected Repository(ApplicationDbContext dbContext)
{
_entity = dbContext.Set<T>();
}
public IList<T> Get(Func<T, bool> where)
{
return _entity.Where(where).ToList();
}
}
然后像下面這樣創建具體的實現:
用戶資料庫
public class UserRepository : Repository<ApplicationUser>
{
public UserRepository(ApplicationDbContext dbContext) : base(dbContext) {}
// Can add any other methods I want that aren't included in IRepository
}
我可能會提供很多服務,所以我不想將每個服務單獨傳遞給控制器,而是想傳遞給可以為我生產存儲庫的單個工廠。
倉庫工廠
public interface IRepositoryFactory
{
T GetRepository<T>() where T : class;
}
public class RepositoryFactory : IRepositoryFactory
{
private readonly IServiceProvider _provider;
public RepositoryFactory(IServiceProvider serviceProvider)
{
_provider = serviceProvider;
}
public T GetRepository<T>() where T : class
{
return _provider.GetRequiredService<T>(); // ERROR: No service for type 'UserRepository' has been registered
}
}
現在,在設置依賴項注入時,我注冊了以下服務:
啟動文件
public void ConfigureServices(IServiceCollection services)
{
// [...]
services.AddScoped<IRepository<ApplicationUser>, UserRepository>();
services.AddScoped<IRepositoryFactory, RepositoryFactory>();
// [...]
}
像這樣在控制器中全部使用:
控制者
public class HomeController : Controller
{
private readonly UserRepository _userRepository;
public HomeController(IRepositoryFactory repositoryFactory)
{
_userRepository = repositoryFactory.GetRepository<UserRepository>(); // ERROR: No service for type 'UserRepository' has been registered
}
// [...]
}
當我在repositoryFactory.GetRepository<UserRepository>()
方法中調用_provider.GetRequiredService<T>()
時,出現上述注釋中的錯誤。
RepositoryFactory
可以順利通過,但是UserRepository
沒有被注冊。 我想念什么? 我嘗試在構造函數之外調用GetRepository
方法,並且嘗試將AddScoped
更改為其他Add
變體(瞬態和Singleton),但無濟於事。
您正在依賴UserRepository
,它是實現而不是接口,所以不好(假設您實際上已在容器中注冊了該接口)。 相反,您需要依賴於接口: IRepository<ApplicationUser>
。 因此,更改您的工廠界面:
public interface IRepositoryFactory
{
IRepository<T> GetRepository<T>() where T : class;
}
實現方式:
public IRepository<T> GetRepository<T>() where T : class
{
return _provider.GetRequiredService<IRepository<T>>(); // ERROR: No service for type 'UserRepository' has been registered
}
和控制器:
public class HomeController : Controller
{
private readonly IRepository<ApplicationUser> _userRepository;
public HomeController(IRepositoryFactory repositoryFactory)
{
_userRepository = repositoryFactory.GetRepository<ApplicationUser>(); // ERROR: No service for type 'UserRepository' has been registered
}
// [...]
}
現在它不起作用,因為您在容器中注冊了IRepository<ApplicationUser>
(實現為UserRepository
),但是您要解析的UserRepository
未注冊(如上所述,您無論如何都不應解析)。
看來我的問題與我對AddScoped
理解有關。 查看文檔, AddScoped
中的兩個類型參數是TService
和TImplementation
。 因此,在上面的啟動類中,我正在注冊的SERVICE是IRepository<ApplicationUser>
而不是ApplicationRepository
。 我注冊的實現是ApplicationRepository
。
為了解決這個問題,我將Startup
類更改為說UserRepository
是正在注冊的服務。
public void ConfigureServices(IServiceCollection services)
{
// [...]
// OLD: services.AddScoped<IRepository<ApplicationUser>, UserRepository>();
services.AddScoped<UserRepository>();
services.AddScoped<IRepositoryFactory, RepositoryFactory>();
// [...]
}
但是這種方法依賴於實現而不是抽象(接口),因此我更進一步,介紹了UserRepository
類的接口並將其注冊在Startup
。
用戶資料庫
public interface IUserRepository : IRepository<ApplicationUser>
{
void DoTheThing();
}
public class UserRepository : Repository<ApplicationUser>, IUserRepository
{
public UserRepository(ApplicationDbContext dbContext) : base(dbContext) {}
public void DoTheThing()
{
}
}
啟動
public void ConfigureServices(IServiceCollection services)
{
// [...]
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IRepositoryFactory, RepositoryFactory>();
// [...]
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.