依赖注入的最佳实践

Yel*_*oon 9 service dependency-injection repository

这是一个关于如何最好地进行DI的问题,因此它不依赖于任何特定的DI/IoC框架,因为,框架应该基于模式和实践而不是相反的方式来选择,不是吗?

我正在做一个项目,其中存储库必须注入服务,服务可能需要多个存储库,我很好奇以下方法之间的利弊:

  1. 在服务构造函数中注入存储库

    public class SomeService : ISomeService
    {
        private IRepository1 repository1;
        private IRepository2 repository2;
    
        public SomeService(IRepository1 repository1, IRepository2 repository2)
        {
              this.repository1 = repository1;
              this.repository2 = repository2;
        }
    
        public void DoThis()
        {
              //Do something with repository1
        }
        public void DoThat()
        {
              //Do something with both repository1 and repository2
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 注入一个自定义上下文类,其中包含任何服务可能需要但是实例化的所有内容(IServiceContext将是BaseService中的受保护字段)

    public class SomeService : BaseService, ISomeService
    {
        public SomeService(IServiceContext serviceContext)
        {
              this.serviceContext= serviceContext;
        }
    
        public void DoThis()
        {
              //Do something with serviceContext.repository1
        }
        public void DoThat()
        {
              //Do something with both serviceContext.repository1 and serviceContext.repository2
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 注入只需要它们的方法

    public class SomeService : ISomeService
    {
        public void DoThis(IRepository1 repository1)
        {
              //Do something with repository1
        }
        public void DoThat(IRepository1 repository1, IRepository2 repository2)
        {
              //Do something with both repository1 and repository2
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

一些指针会受到赞赏,而且在评估这些替代方案时我应该考虑哪些方面?

Ste*_*ven 8

注入依赖项的首选方法是构造函数注入.

方法注入不太理想,因为这将很快导致必须传递从服务到服务的许多依赖关系,并且它将导致实现细节(依赖关系)通过API(您的方法)泄漏.

选项1和2都是构造函数注入,这很好.如果您发现自己必须在构造函数中注入太多依赖项,则会出现问题.您违反了单一责任原则,或者您缺少某种聚合服务,这就是您在选项2中所做的.

但是,在您的情况下,您的IServiceContext 聚合服务将多个存储库组合在一起.一个类后面的许多存储库闻起来像是一个工作单元.只需添加一个Commit方法IServiceContext,您一定会有一个工作单元.想一想:你不想注入IUnitOfWork你的服务吗?