.NET Core异常:检测到类型为

时间:2018-12-04 21:29:29

标签: c# asp.net-core dependency-injection inversion-of-control ioc-container

最近我问了一个有关软件体系结构的问题

Should service call another service or repository directly?

在回答之后,我对应用程序进行了重组和重构。用一种简单的方式,我的服务彼此调用,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和CompaniesHelper。 它们全部检查用户权限并从适当的存储库(EmployeesRepository等的EmployeesHelper)中调用方法。 此外,在这一层上,我们具有创建更多“复杂”对象的方法,这些对象是由许多实体组成的对象。 例如,CompaniesHelper具有显示服务销售最多的前五家公司的方法。 数据将显示在一个屏幕上,因此应由一个API请求生成并作为JSON返回。 CompaniesHelper方法中的ShowCompaniesWithServices调用CompaniesHelper方法和EmployeesHelper方法。 在第二面,我们有EmployeesHelper,它实现了方法以返回当月最高雇员的复杂对象, 他们的顶级服务和所工作的公司,因此需要Comapnies Helper。

如何解决这种循环依赖关系?是否有解决的设计模式?

3 个答案:

答案 0 :(得分:1)

因此,我认为服务不应注入其他服务。

我认为每个服务应该能够独立存在并仅提供其负责的数据。如果IStudentService的使用者也需要来自两个来源的数据,则也可以是IClassService的使用者。

答案 1 :(得分:0)

您有两种方法:

  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)

答案 2 :(得分:0)

我不能完全确定我解决此问题的方法是否很干净,但是对我来说效果很好。当遇到循环依赖问题时,我从“依赖注入”中删除了该服务,只是将该服务作为参数传递给需要它的函数。

因此,当您调用该方法时,它看起来像这样:

// Inside the Student service
var result = _classService.GetClassStudents(classId, this)

可能不适用于每个人,但就我而言,我的设置非常简单,因此我没有深入研究。

希望这会有所帮助。