首页 > 解决方案 > .NET Core 异常:检测到类型服务的循环依赖项

问题描述

最近问了一个关于软件架构的问题

服务应该直接调用另一个服务或存储库吗?

在得到那个答案之后,我重新组织并重构了我的应用程序。以一种简单的方式,我的服务相互调用,StudentService 需要 ClassService(例如获取平均班级分数),ClassService 需要 StudentService(获取分配给班级的学生)。类(简化)如下所示:

public class StudentService : IStudentService
{
    protected readonly IClassService ClassService;
    public StudentService(IClassService classService)
    {
        ClassService = classService;
    }
}

public class ClassService : IClassService
{
    protected readonly IStudentService StudentService;
    public ClassService(IStudentService studentService)
    {
        StudentService = studentService;
    }
}

服务在 .NET Core 的 DI 容器中注册

services.AddTransient<IStudentService, StudentService>();
services.AddTransient<IClassService, ClassService>();

解决期间

var studentService = app.ApplicationServices.GetService<IStudentService>();

我得到一个异常检测到类型服务的循环依赖...

我了解这里的实现问题,但我不知道如何解决这里的架构问题。

你能提供一些建议吗?

编辑:好的,我有更现实的案例,例如员工、服务和公司。我们有带有抽象通用 CRUD 存储库的存储库层。然后我们有派生类:EmployeesRepository ServicesRepository 和 CompaniesRepository。EmployeesRepository 实现方法:GetTopEmployeesOfTheMonth ServicesRepository 实现方法:GetTopServicesForEmployees CompaniesRepository 实现方法:GetCompaniesWithTopIncome

在上面的层(我们称之为业务层),我们有相同的结构:抽象的通用 CRUD 助手,例如检查用户权限并从 CRUD 存储库调用方法。然后我们派生了EmployeesHelper、ServicesHerlper 和CompanyHelper。所有这些都检查用户权限并从适当的存储库调用方法(来自EmployeesRepository 的EmployeesHelper 等)。此外,在这一层上,我们有创建更“复杂”对象的方法——由许多实体组成的对象。例如,CompanyHelper 有方法显示销售服务最多的前五名公司。数据将显示在一个屏幕上,因此它应该由一个 API 请求生成并以 JSON 形式返回。CompaniesHelper 方法中的 ShowCompaniesWithServices 调用 CompaniesHelper 方法和EmployeesHelper 方法。在第二面,

如何解决这种循环依赖?是否有任何设计模式可以解决它?

标签: c#asp.net-coredependency-injectioninversion-of-controlioc-container

解决方案


你有两种方法:

  1. 编写不需要从 StudentService 调用 ClassService(或从 ClassService 调用 StudentService)的代码

  2. 创建第三类:

    public class StudentService: IStudentService
    {
        private readonly IClassSharedSerive _classSharedService;
        ...
    }
    
    public class ClassService: IClassService
    {
        private readonly IClassSharedSerive _classSharedService;
        private readonly IStudentService _studentService;
        ...
    }
    
    public class ClassSharedService: IClassSharesService
    {
        ... without references to IClassService and IStudentService
    }
    

但是,在大多数情况下,需要正确编写 StudentService 和 ClassService(方式 1)


推荐阅读