使用通用存储库将autofac与webapi绑定
本文关键字:webapi 绑定 autofac 存储 | 更新日期: 2023-09-27 18:26:22
我正在尝试将autofac与存储库一起使用,并尝试添加一些泛型,以减少我正在编写的重复代码的数量。然而,我正在兜圈子,试图让autofac为我工作
所以我创建了一个域服务和接口来处理我们的标准crud操作
public class DomainService<T>:IDomainService<T>
{
protected readonly IDomainService<T> Repository;
public DomainService(IDomainService<T> repository)
{
Repository = repository;
}
public IQueryable<T> GetQueryable()
{
return Repository.GetQueryable();
}
public virtual Task<T> Add(T entity)
{
return Repository.Add(entity);
}
接口:
public interface IDomainService<T>
{
IQueryable<T> GetQueryable();
Task<T> Add(T entity);
Task<bool> Delete(T entity);
Task<T> Update(T entity);
Task<T> GetById(int id);
Task<T> GetByUID(Guid id);
}
我正在使用我的回购没有什么特别的
public class SkillRepository : DomainService<Skill>, ISkill
{
private DataContext _db = new DataContext();
private readonly ILogger _log = null;
public SkillRepository(IDomainService<Skill> repository, ILogger log) : base(repository)
{
_log = log;
}
}
最后,在我连接autofac:的地方
var builder = new ContainerBuilder();
// Register the Web API controllers.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Register other dependencies.
builder.Register(c => new Logger()).As<ILogger>().InstancePerApiRequest();
builder.RegisterType<SkillRepository>()
.As<IDomainService<Skill>>()
.As<ISkill>()
.InstancePerRequest();
// Build the container.
var container = builder.Build();
// Create the depenedency resolver.
var resolver = new AutofacWebApiDependencyResolver(container);
// Configure Web API with the dependency resolver.
GlobalConfiguration.Configuration.DependencyResolver = resolver;
我的web api控制器看起来像
public class SkillsController : BaseController<Skill>
{
private readonly ISkill _skillRepository;
public SkillsController(SkillRepository skillRepository) : base(skillRepository)
{
_skillRepository = skillRepository;
}
}
基本控制器
public abstract class BaseController<TEntity> : ApiController
where TEntity : new()
{
protected readonly IDomainService<TEntity> DomainService;
protected BaseController(IDomainService<TEntity> domainService)
{
DomainService = domainService;
}
我得到一个例外:
"找不到具有的构造函数类型上的"Autofac.Core.Activators.Reflection.DefaultConstructorFinder"Api.EndPoints.Skills.SkillsController"可以使用可用的服务和参数:''''无法解析参数构造函数的"Domain.Repository.SkillRepository SkillRepository"'Void.ctor(Domain.Repository.SkillRepository)'。"
有什么明显的事情表明我做错了吗?
它无法解析依赖项,因为它正在查找具体类型,但您从未将SkillsRepository
注册为该类型。现在您可以更改注册来注册具体类型,但这不是最好的方法。
更好的方法是将SkillsReserve注册为其接口:
builder.RegisterType<SkillRepository>()
.As<ISkillsRepository>()
.InstancePerRequest();
并定义ISkillsRepository
以继承所有其他接口,如ISkill
。
public interface ISkillsRepository : ISkill, IDomainService<Skill> { }
不要将对象注册为具体类型,也不要依赖于构造函数中的具体类型
public SkillsController(ISkillRepository skillRepository) :
base(skillRepository) ...
如果使用具体类型作为依赖项,则会创建无法使用mocking框架进行测试的类。
你对SkillRepository : DomainService<Skill>, ISkill
的使用也令人困惑。为什么它既是一项技能,又是一项技能领域服务?没有多大意义。
异常明确指出:
无法解析构造函数"Void.ctor(Domain.IDomainService`1[Model.Skill],Domain.Interfaces.ISkill)"的参数"Domain.Interfaces.ISkill skillRepository"。
您只注册了IDomainService
。但没有ISkill
(该行有注释)。
此外,为什么ctor需要2个参数?SkillRepository
同时实现IDomainService<Skill>
和ISkill
,因此您应该能够传递它:
public SkillsController(SkillRepository skillRepository) : base(skillRepository)
p.S.
我会这样命名:
public class SkillRepository : ISkillRepository, IDomainService<Skill>
我更喜欢所有的东西都是复数(SkillsControllers,SkillsRepository)或单数(SkillController,SkillRepository)。
在我看来,您应该首先对类的名称进行排序,这会使代码本身难以理解。其次,您的存储库正在实现域服务接口和ISkill,诸如此类的事情会增加更多的混乱。我敢肯定,如果你把课程安排得当,你就会找到解决问题的办法。例如,ApiController应该使用域服务,域服务应该使用存储库,存储库应该处理实体。
public class SkillsDomainService:ISkillsDomainService
{
public void AddSkill(string name){}
public void DeleteSkillById(int id){}
..... etc
}
public class Repository:IRepository
{
public T Get(int id){}
public IEnumerable<T>GetAll(){}
}
然后,您需要将接口绑定到ioc中分类的具体接口。我很确定事情应该是这样的。