C# 使用通用存储库将autofac与webapi绑定

C# 使用通用存储库将autofac与webapi绑定,c#,asp.net-web-api,dependency-injection,autofac,C#,Asp.net Web Api,Dependency Injection,Autofac,我正在尝试将autofac与一个存储库一起使用,我正在尝试添加一些泛型,以减少我正在编写的重复代码的数量。然而,我正在绕圈尝试让autofac为我工作 因此,我创建了一个domainservice和接口来处理我们的标准crud操作 public class DomainService<T>:IDomainService<T> { protected readonly IDomainService<T> Repository; public D

我正在尝试将autofac与一个存储库一起使用,我正在尝试添加一些泛型,以减少我正在编写的重复代码的数量。然而,我正在绕圈尝试让autofac为我工作

因此,我创建了一个domainservice和接口来处理我们的标准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);
    }
公共类域服务:IDomainService
{
受保护的只读IDomainService存储库;
公共域服务(IDomainService存储库)
{
存储库=存储库;
}
公共IQueryable GetQueryable()
{
返回Repository.GetQueryable();
}
公共虚拟任务添加(T实体)
{
返回Repository.Add(实体);
}
接口:

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);
}
公共接口IDomainService
{
IQueryable GetQueryable();
任务添加(T实体);
任务删除(T实体);
任务更新(T实体);
任务GetById(int-id);
任务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;
    }
}
public class SkillRepository:DomainService,ISkill
{
私有数据上下文_db=new DataContext();
私有只读ILogger _log=null;
public SkillRepository(IDomainService repository,ILogger日志):基本(存储库)
{
_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;
var builder=newcontainerbuilder();
//注册Web API控制器。
RegisterAppController(Assembly.getExecutionGassembly());
//注册其他依赖项。
builder.Register(c=>newlogger()).As().InstancePerApiRequest();
builder.RegisterType()
.As()
.As()
.InstancePerRequest();
//构建容器。
var container=builder.Build();
//创建依赖解析程序。
var resolver=新的AutofacWebApidenceResolver(容器);
//使用依赖项解析程序配置Web API。
GlobalConfiguration.Configuration.DependencyResolver=解析程序;
我的web api控制器看起来像

public class SkillsController : BaseController<Skill>
{
    private readonly ISkill _skillRepository;

    public SkillsController(SkillRepository skillRepository) : base(skillRepository)
    {
        _skillRepository = skillRepository;
    }
}
公共类技能控制器:BaseController
{
私有只读ISkill存储库;
公共SkillsController(SkillRepository SkillRepository):基础(SkillRepository)
{
_skillRepository=skillRepository;
}
}
基站控制器

public abstract class BaseController<TEntity> : ApiController
    where TEntity : new()
{
    protected readonly IDomainService<TEntity> DomainService;

    protected BaseController(IDomainService<TEntity> domainService)
    {
        DomainService = domainService;
    }
<代码>公共抽象类BaseController:ApiController where tenty:new() { 受保护的只读IDomainService DomainService; 受保护的BaseController(IDomainService domainService) { DomainService=DomainService; } 我得到一个例外:

“没有找到具有 类型上的“Autofac.Core.Activators.Reflection.DefaultConstructorFinder” “Api.EndPoints.Skills.SkillsController”可以通过调用 可用服务和参数:\\n无法解析参数 构造函数的“Domain.Repository.SkillRepository SkillRepository” 'Void.ctor(Domain.Repository.SkillRepository)'


是否有明显的事情表明我做错了?

异常清楚地表明:

无法解析构造函数Void.ctor(Domain.IDomainService`1[Model.Skill],Domain.Interfaces.ISkill')的参数“Domain.Interfaces.ISkill skillRepository”

您只注册了
IDomainService
。但没有
ISkill
(该行已注释)

另外,为什么ctor需要两个参数?
SkillRepository
实现了
IDomainService
ISkill
,因此您应该能够传递它:

public SkillsController(SkillRepository skillRepository) : base(skillRepository)
附言

我可以这样命名:

public class SkillRepository : ISkillRepository, IDomainService<Skill>
public class SkillRepository:ISkillRepository,IDomainService

我更喜欢所有东西都是复数(SkillsController,SkillsRepository)或单数(SkillController,SkillRepository).

它无法解决依赖关系,因为它正在查找具体类型,但您从未注册过
SkillsRepository
。现在您可以更改注册以注册具体类型,但这不是最好的方法

更好的方法是将SkillsRepository注册为其接口:

builder.RegisterType<SkillRepository>()
    .As<ISkillsRepository>()
    .InstancePerRequest();
不要将对象注册为具体类型,也不要依赖构造函数中的具体类型。

  public SkillsController(ISkillRepository skillRepository) : 
      base(skillRepository) ...
如果使用具体类型作为依赖项,则会创建无法使用模拟框架进行测试的类


您使用的
SkillRepository:DomainService,ISkill也令人困惑。为什么它既是技能又是技能的域服务?没有多大意义。

在我看来,您应该首先为您的类排序名称,这使得代码本身很难理解。其次,您的存储库正在实现域服务iinterface和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(){}
}
public class SkillsDomainService:ISkillsDomainService
{
public void AddSkill(字符串名){}
public void DeleteSkillById(int-id){}
等
}
公共类存储库:IRepository
{
公共T Get(int id){}
公共IEnumerableGetAll(){}
}

然后你需要将你的接口绑定到ioc中的具体类。我很确定事情应该是这样的。

Hi@abatishchev我对上面的代码global.asax做了修改。你能找出哪里出了问题吗?我还没有设法解决它谢谢Ian的详细解释。听起来我做错了一些事情。我有更新了上面的代码域服务,以尝试展示更多我正在尝试做的事情。本质上,我尝试使用DomainService作为一种方式,因为我必须在每个存储库上实现IDomainService。因为代码是相同的,并且为每个repo编写都很枯燥。这有意义吗?有意义,但使用Composition rath可能会更好此外,当你避免“脂肪控制器”(通常是
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(){}
}