问题描述
Registering repository using generics with multiple types <T, T> c# dotnet core
我正在创建一个通用存储库,如下所示:
public interface IRepository<T> where T : class
{
Task<T> GetById(int id);
Task Add(T entity);
void AddRange(IEnumerable<T> entities);
Task<int> Save();
Task Delete(int id);
void Delete(T entity);
T Update(T entity);
}
public abstract class Repository<T, TContext> : IRepository<T> where T :
class where TContext : DbContext
{
protected readonly TContext _context;
private DbSet<T> _table;
protected Repository(TContext context)
{
_context = context;
_table = _context.Set<T>();
}
// implementation
}
我想将任何 DBcontext
传递给实现,具体的实现应该是这样的:
public interface ICouponRepository : IRepository<Coupon>
{
Task RedeemCoupon(int id, Guid userId);
}
public class CouponRepository : Repository<Coupon, CouponApiDBContext>, ICouponRepository
{
private readonly CouponApiDBContext _couponApiDBContext;
protected CouponRepository(CouponApiDBContext couponApiDBContext) : base(couponApiDBContext)
{
_couponApiDBContext = couponApiDBContext;
}
public Task RedeemCoupon(int id, Guid userId)
{
throw new NotImplementedException();
}
}
然后我按如下方式注册这两项服务:
services.AddTransient(typeof(IRepository<>), typeof(Repository<,>))
.AddTransient<ICouponRepository, CouponRepository>()
但是我可以实例化通用存储库,但出现以下错误:
An unhandled exception of type 'System.ArgumentException' occurred in xxx.dll: 'Cannot instantiate implementation type 'xxx.Repositories.Repository2[T,TContext]' for service type 'xxx.Repositories.IRepository1[T]'.'
答案
立即想到三件事。
第一个与您的问题无关,但 CouponRepository
不应该有自己的 _couponApiDBContext
成员,它可以访问基类 TContext
- 这就是首先让它通用的全部意义。
第二个是您在 ICouponRepository
中使用 RedeemCoupon
方法专门化了 IRepository<Coupon>
- 因此您注册开放泛型类型的机会为零,只是期望 DI
知道您所追求的实际接口。
您只剩下删除此 AddTransient(typeof(IRepository<>), typeof(Repository<,>))
- 这是毫无意义的,因为 DI
无论如何都无法实例化抽象类,这是错误消息的根本原因,您应该注册 AddTransient<ICouponRepository, CouponRepository>()
并在您需要的地方请求 ICouponRepository
- 您不能请求 IRepository<Coupon>
因为它没有我认为您需要的 RedeemCoupon
方法。