C# 不为类型'提供服务;MyType';已注册

C# 不为类型'提供服务;MyType';已注册,c#,.net,dependency-injection,.net-core,asp.net-core-2.0,C#,.net,Dependency Injection,.net Core,Asp.net Core 2.0,我有一个通用的存储库体系结构,如下所示: 存储库 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>

我有一个通用的存储库体系结构,如下所示:

存储库

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 interface IUserRepository : IRepository<ApplicationUser>
{
    void DoTheThing();
}

public class UserRepository : Repository<ApplicationUser>, IUserRepository
{
    public UserRepository(ApplicationDbContext dbContext) : base(dbContext) {}

    public void DoTheThing()
    {

    }
}
公共接口i假设,其中T:class
{
IList Get(Func where);
}
公共抽象类存储库:IRepository,其中T:class
{
私有只读数据库集实体;
受保护的存储库(ApplicationDbContext dbContext)
{
_entity=dbContext.Set();
}
公共IList Get(Func where)
{
返回_entity.Where(Where.ToList();
}
}
然后创建如下具体实现:

UserRepository

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 interface IUserRepository : IRepository<ApplicationUser>
{
    void DoTheThing();
}

public class UserRepository : Repository<ApplicationUser>, IUserRepository
{
    public UserRepository(ApplicationDbContext dbContext) : base(dbContext) {}

    public void DoTheThing()
    {

    }
}
公共类用户存储库:存储库
{
公共用户存储库(ApplicationDbContext dbContext):基本(dbContext){}
//可以添加IRepository中未包含的任何其他方法
}
我可能会有很多服务,所以我不想让每个服务都单独传递到控制器中,我想我应该尝试传递一个可以为我生成存储库的工厂

存储工厂

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 interface IUserRepository : IRepository<ApplicationUser>
{
    void DoTheThing();
}

public class UserRepository : Repository<ApplicationUser>, IUserRepository
{
    public UserRepository(ApplicationDbContext dbContext) : base(dbContext) {}

    public void DoTheThing()
    {

    }
}
公共接口IRepositoryFactory
{
T GetRepository(),其中T:class;
}
公共类存储工厂:IRepositoryFactory
{
专用只读服务器ViceProvider(提供程序);
公共存储工厂(IServiceProvider服务提供商)
{
_提供者=服务提供者;
}
public T GetRepository(),其中T:class
{
return _provider.GetRequiredService();//错误:尚未注册“UserRepository”类型的服务
}
}
现在,在设置依赖项注入时,我注册了如下服务:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    // [...]

    services.AddScoped<IRepository<ApplicationUser>, UserRepository>();
    services.AddScoped<IRepositoryFactory, RepositoryFactory>();

    // [...]
}
public void配置服务(IServiceCollection服务)
{
// [...]
services.addScope();
services.addScope();
// [...]
}
所有这些都在控制器中使用,如下所示:

控制器

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
    }

    // [...]
}
公共类HomeController:控制器
{
私有只读用户存储库_UserRepository;
公共家庭控制器(IRepositoryFactory repositoryFactory)
{
_userRepository=repositoryFactory.GetRepository();//错误:尚未注册“userRepository”类型的服务
}
// [...]
}
当我在
repositoryFactory.GetRepository()
方法中调用
\u provider.GetRequiredService()
时,我在上面的注释中得到了错误


RepositoryFactory
运行正常,但是
UserRepository
没有注册。我错过了什么?我尝试在构造函数之外调用
GetRepository
方法,并尝试将
AddScoped
更改为其他
Add
变体(瞬态和单例),但没有效果。

您依赖于
UserRepository
,这是实现而不是接口,这不好(假设您实际上已在容器中注册了该接口)。相反,您需要依赖接口:
IRepository
。因此,请更改您的工厂接口:

public interface IRepositoryFactory
{
    IRepository<T> GetRepository<T>() where T : class;
}
公共接口IRepositoryFactory
{
IRepository GetRepository(),其中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 IRepository GetRepository(),其中T:class
{
return _provider.GetRequiredService();//错误:尚未注册“UserRepository”类型的服务
}
和控制器:

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
    }

    // [...]
}
公共类HomeController:控制器
{
私有只读IRepository用户存储库;
公共家庭控制器(IRepositoryFactory repositoryFactory)
{
_userRepository=repositoryFactory.GetRepository();//错误:尚未注册“userRepository”类型的服务
}
// [...]
}

现在它不起作用了,因为您在容器中注册了
IRepository
(实现是
UserRepository
),但是您尝试解析的
UserRepository
没有注册(如上所述,您无论如何都不应该解析它).

看起来我的问题与我对
AddScoped
的理解有关。查看文档,
AddScoped
中的两个类型参数是
TService
TImplementation
。因此在我上面的启动类中,我注册的服务是
irepositionory
,而不是
ApplicationRepository
。我正在注册的实现是
ApplicationRepository

为了解决这个问题,我更改了我的
Startup
类,说
UserRepository
是正在注册的服务

public void ConfigureServices(IServiceCollection services)
{
    // [...]

    // OLD: services.AddScoped<IRepository<ApplicationUser>, UserRepository>();
    services.AddScoped<UserRepository>();
    services.AddScoped<IRepositoryFactory, RepositoryFactory>();

    // [...]
}
启动

public void ConfigureServices(IServiceCollection services)
{
    // [...]

    services.AddScoped<IUserRepository, UserRepository>();
    services.AddScoped<IRepositoryFactory, RepositoryFactory>();

    // [...]
}
public void配置服务(IServiceCollection服务)
{
// [...]
services.addScope();
services.addScope();
// [...]
}

我们都在同一时间输入答案,但我认为我们说的基本上是一样的。这就是解决方案。