我是 .Net 的新手,我正在尝试从头开始构建一个骨架项目。
首先,我编写了代表基本实体的IEntity类,简单易行如下:
public interface IEntity
{
int Id { get; set; }
}
然后我做了一个存储库界面,看起来像这样:
public interface IRepository<T> where T : class, IEntity
{
//...... some methods
}
以及该接口的基本实现,如下所示:
public class EFCoreRepository<TEntity, TContext> : IRepository<TEntity>
where TEntity : class, IEntity
where TContext : DBContext
{
protected readonly TContext _context;
public EFCoreRepository(TContext context)
{
this._context = context;
}
// ...... some methods
}
一个服务接口,看起来像这样
public interface IService<TEntity> where TEntity : class, IEntity
{
// ...... some methods
}
以及该服务接口的基本实现,如下所示:
public class EFCoreService<TEntity, TRepo> : IService<TEntity>
where TEntity : class, IEntity
where TRepo : EFCoreRepository<TEntity, DBContext>
{
protected readonly TRepo _repository;
public EFCoreService(TRepo repository) {
_repository = repository;
}
// ...... some methods
}
我像这样在 program.cs 中注册了它们:
builder.Services.AddScoped<IRepository<IEntity>, EFCoreRepository<IEntity, DBContext>>();
builder.Services.AddScoped<IService<IEntity>, EFCoreService<IEntity, EFCoreRepository<IEntity, DBContext>>>();
您可能会注意到它是
DBContext
而不是 DbContext
。这不是错字,DBContext
是我定制的课程,扩展了DbContext
.
当我尝试构建项目时,出现了这个运行时错误:
Some services are not able to be constructed (Error while validating the service descriptor
ServiceType: IService<IEntity>
Lifetime: Scoped
ImplementationType: EFCoreService<IEntity,EFCoreRepository<IEntity,DBContext>>
Unable to resolve service for type EFCoreRepository<IEntity,DBContext> while attempting to activate EFCoreService<IEntity,EFCoreRepository<IEntity,DBContext>>
谁能找到这个错误的原因?任何建议将不胜感激。
------------------------------------ 补充问题-------- --------------------------
上面我想做的是注册一个公共服务,这样任何实现了基础服务的服务都可以有相应的实现方法。例如,如果有一个名为
Item
的实体,它的服务接口和实现是从基础服务扩展的,它们应该自动注册(准备作为依赖项注入)并具有基类实现的方法,如这个:
public interface IItemService : IService<Item>
{
}
public class ItemService : EFCoreService<Item, ItemRepository>
{
public ItemService(ItemRepository repository) : base(repository)
{
}
}
是否可以通过上面的代码实现?
你可以试试下面的代码。
创建一个
DBContext
像表格一样进行测试。
public class DBContext
{
public IEnumerable<Product> products = new List<Product>()
{
new Product(){ Id=1 ,Name="Coke"},
new Product(){ Id=2,Name="Pepsi"}
};
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
将
TContext
添加到IRepository
并创建一个get()
方法进行测试。 (应该得到第一个产品名称是“可乐”)
public class EFCoreRepository<TEntity, TContext> : IRepository<TEntity, TContext> where TEntity : class, IEntity
where TContext : DBContext
{
protected readonly TContext _context;
public EFCoreRepository(TContext context)
{
this._context = context;
}
// ...... some methods
public string get()
{
return _context.products.FirstOrDefault().Name;
}
}
所以
IRepository.cs
变了
public interface IRepository<TEntity, TContext> where TEntity : class, IEntity where TContext : class
{
string get();
}
在
EFCoreService
中,注入EFCoreRepository
而不是添加泛型TRepo
public class EFCoreService<TEntity> : IService<TEntity>
where TEntity : class, IEntity
{
private readonly EFCoreRepository<TEntity, DBContext> _repository;
public EFCoreService(EFCoreRepository<TEntity,DBContext> repository)
{
this._repository = repository;
}
// ...... some methods
public string get()
{
return _repository.get();
}
}
所以
IService
也变了
public interface IService<TEntity> where TEntity : class, IEntity
{
// ...... some methods
string get();
}
注册服务
program.cs
.
builder.Services.AddScoped<DBContext>();
builder.Services.AddScoped(typeof(EFCoreRepository<,>));
builder.Services.AddScoped(typeof(IRepository<,>), typeof(EFCoreRepository<,>));
builder.Services.AddScoped(typeof(IService<>), typeof(EFCoreService<>));
测试控制器
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IService<Item> _service;
public ValuesController(IService<Item> service)
{
this._service = service;
}
[HttpGet("test")]
public string test()
{
return _service.get();
}
}