<分区>
我知道其他人已经遇到了同样的问题,但我找不到任何令人满意的解决方案,所以我在这里询问其他想法。
我的业务逻辑包含在这样的服务层中:
public class RoomService : IRoomService
{
private readonly IRoomRepository _roomRepository;
private readonly ICourseService _courseService;
public RoomService(IRoomRepository roomRepository, ICourseService courseService)
{
_roomRepository = roomRepository ?? throw new ArgumentNullException(nameof(roomRepository));
_courseService = courseService ?? throw new ArgumentNullException(nameof(courseService));
}
public Task DeleteRoomAsync(string id)
{
// Check if there are any courses for this room (requires ICourseService)
// Delete room
}
}
public class CourseService : ICourseService
{
private readonly ICourseRepository _courseRepository;
private readonly IRoomService _roomService;
public CourseService(ICourseRepository courseRepository, IRoomService roomService)
{
_courseRepository = courseRepository ?? throw new ArgumentNullException(nameof(courseRepository));
_roomService = roomService ?? throw new ArgumentNullException(nameof(roomService));
}
public Task GetAllCoursesInBuilding(string buildingId)
{
// Query all rooms in building (requires IRoomService)
// Return all courses for these rooms
}
}
这只是一个例子。在这种情况下,可能有避免服务相互依赖的变通办法,但我过去遇到过多种其他情况,没有任何干净的变通办法。
如您所见,这两个服务相互依赖,并且由于循环依赖,依赖注入(inject)将失败。
现在我可以想出两种方法来解决这个问题:
方案一
我可以在需要它们的服务方法中解决服务依赖关系,而不是将服务依赖关系注入(inject)服务构造函数:
public class RoomService : IRoomService
{
private readonly IRoomRepository _roomRepository;
private readonly IServiceProvider _serviceProvider;
public RoomService(IRoomRepository roomRepository, IServiceProvider serviceProvider)
{
_roomRepository = roomRepository ?? throw new ArgumentNullException(nameof(roomRepository));
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
public Task DeleteRoomAsync(string id)
{
ICourseService courseService = _serviceProvider.GetRequiredService<ICourseService>();
// Check if there are any courses for this room (requires ICourseService)
// Delete room
}
}
问题:这使得单元测试变得更加困难,因为我需要注入(inject)一个模拟的 IServiceProvider
,它能够将我的 ICourseService
解析到类构造函数中.在编写单元测试时也不是很清楚,每个服务方法需要哪些服务,因为这完全取决于实现。
解决方案2
服务方法可能需要 ICourseService
作为方法参数从 Controller 传入:
public Task DeleteRoomAsync(ICourseService courseService, string id)
{
// Check if there are any courses for this room (requires ICourseService)
// Delete room
}
问题:现在我的 Controller 需要了解服务方法的实现细节:DeleteRoomAsync
需要一个 ICourseService
对象来做它的工作。
我认为这不是很干净,因为 DeleteRoomAsync
的要求将来可能会改变,但方法签名不应该。
您能想到任何更清洁的替代解决方案吗?