英文:
Repository/Service Pattern Issues .NET Core
问题
我有一些架构问题,正在努力解决。我需要找到更好的方法来完成我的目标。
以下是我的服务/存储库的简要示意图。我的问题是在激活它们时出现了循环引用。问题在于每个服务中都有我需要的代码,例如在LoadService中,我可能需要触发CustomerService中的方法,反之亦然。
需要帮助理解这里的最佳方法。我正在尽量将这些服务分离职责原则(SRP)。
LoadRepository
public class LoadRepository
{
private readonly DBContext _DBContext;
public LoadRepository(DBContext DBContext)
{
_DBContext = DBContext;
}
public override DbSet<LoadEntity> LoadDbSet()
{
return _DBContext.Load;
}
}
LoadService
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly ICustomerService _customerService;
public LoadService(
LoadRepository loadRepository,
ICustomerService customerService
)
{
_loadRepository = loadRepository;
_customerService = customerService;
}
}
CustomerRepository
public class CustomerRepository
{
private readonly DBContext _DBContext;
public CustomerRepository(DBContext DBContext)
{
_DBContext = DBContext;
}
public override DbSet<CustomerEntity> LoadDbSet()
{
return _DBContext.Customer;
}
}
CustomerService
public class CustomerService
{
private readonly CustomerRepository _customerRepository;
private readonly ILoadService _loadService;
public CustomerService(
CustomerRepository customerRepository,
ILoadService loadService
)
{
_customerRepository = customerRepository;
_loadService = loadService;
}
}
英文:
Having some architecture issues that I'm trying to work through. I need to find a better way to do what I'm trying to do.
Below is a brief mockup of how my services/repos look. My problem is I am getting a circular reference when activating them. The problem is there is code in each service that I need for example in the LoadService I may need to trigger a method in the CustomerService and vice versa.
Need help to understand the best approach here. I am trying to get these services in a SRP as much as possible.
LoadRepository
public class LoadRepository
{
private readonly DBContext _DBContext;
public LoadRepository(DBContext DBContext)
{
_DBContext = DBContext;
}
public override DbSet<LoadEntity> LoadDbSet()
{
return _DBContext.Load;
}
}
LoadService
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly ICustomerService _customerService;
public LoadService(
LoadRepository loadRepository,
ICustomerService customerService
)
{
_loadRepository = loadRepository;
_customerService = customerService;
}
}
CustomerRepository
public class CustomerRepository
{
private readonly DBContext _DBContext;
public CustomerRepository(DBContext DBContext)
{
_DBContext = DBContext;
}
public override DbSet<CustomerEntity> LoadDbSet()
{
return _DBContext.Customer;
}
}
CustomerService
public class CustomerService
{
private readonly CustomerRepository _customerRepository;
private readonly ILoadService _loadService;
public CustomerService(
CustomerRepository customerRepository,
ILoadService loadService
)
{
_customerRepository = customerRepository;
_loadService = loadService;
}
}
答案1
得分: 1
在我的个人经验中,最好避免相互引用相同级别的依赖关系。将常见功能移到一些辅助类中,或将所有所需的存储库注入到相应的服务中。例如:
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly CustomerRepository _customerRepository;
public LoadService(
LoadRepository loadRepository,
CustomerRepository customerRepository
)
{
_loadRepository = loadRepository;
_customerRepository = customerRepository;
}
}
另一种减轻问题的方法(如果当前重构过于复杂)是使用惰性注入,例如通过使用工厂以 Func
作为参数:
// 默认的依赖注入不提供自动的 Func 注册
Services.AddScoped<Func<ICustomerService>>(sp => () => sp.GetRequiredService<ICustomerService>)
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly Func<ICustomerService> _customerServiceFactory;
public LoadService(
LoadRepository loadRepository,
Func<ICustomerService> customerService
)
{
_loadRepository = loadRepository;
_customerServiceFactory = customerService;
}
}
当需要时,调用工厂 - _customerServiceFactory().SomeMethod()
。请注意,这种方法可能会导致递归调用时栈溢出,例如 ICustomerService.Foo()
调用 ILoadService.Bar()
,后者又调用 ICustomerService.Foo()
,这种情况只能在运行时捕获到。
英文:
In my personal experience it is better to avoid dependencies on the same level referencing each other. Move common functionality into some helper classes and/or inject all needed repositories into the corresponding services. For example :
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly CustomerRepository _customerRepository;
public LoadService(
LoadRepository loadRepository,
CustomerRepository customerRepository
)
{
_loadRepository = loadRepository;
_customerRepository = customerService;
}
}
Another approach to mitigate the problem (if currently refactoring is to much of headache) - use lazy injection via factories, for example something like the following using factory via Func
:
// default DI does not provide automatic Func registration
Services.AddScoped<Func<ICustomerService>>(sp => () => sp.GetRequiredService<>(ICustomerService))
public class LoadService
{
private readonly LoadRepository _loadRepository;
private readonly Func<ICustomerService> _customerServiceFactory;
public LoadService(
LoadRepository loadRepository,
Func<ICustomerService> customerService
)
{
_loadRepository = loadRepository;
_customerServiceFactory = customerService;
}
}
And when it is needed invoke the factory - _customerServiceFactory().SomeMethod()
. Though note that this method can result in SO if you have cycle in invocations (i.e. ICustomerService.Foo()
calls ILoadService.Bar()
which calls ICustomerService.Foo()
) which can be caught only in runtime.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论