我想要一些建议,解决依赖注入在‘间接注入’的上下文.请考虑下面的示例.
假设我有三个接口,即:IAdminService
、IEmailService
和IBillService
.每个都有单一的实现类型,即AdminService
、EmailService
和BillService
.
下面是一个IAdminService
及其实现类型的示例.
public interface IAdminService
{
void DoSomething();
}
public class AdminService : IAdminService
{
IServiceA A { get; }
public AdminService (IServiceA A)
{
this.A = A;
}
public void DoSomething(){
{
A.QuerySomething();
}
}
最重要的是,我有一个IServiceManagement
的抽象,它利用了延迟加载.请参见下文.
public interface IServiceManagement
{
IAdminService AdminService{ get; }
IEmailService IEmailService{ get; }
IBillService BillService { get; }
}
public sealed class ServiceManagement : IServiceManagement
{
private readonly Lazy<IAdminService> _adminService;
private readonly Lazy<IEmailService> _emailService;
private readonly Lazy<IBillService> _billService;
public ServiceManagement (
IServiceA ServiceA,
IServiceB ServiceB,
IserviceC serviceC,
...)
{
_adminService = new Lazy<IAdminService>(() => new AdminService(ServiceA));
_emailService = new Lazy<IEmailService>(() => new EmailService(...));
_billService = new Lazy<IBillService>(() => new BillService(...));
}
public IAdminService AdminService => _adminService.Value;
public IEmailService EmailService => _emailService.Value;
public IBillService BillService => _billService.Value;
}
服务注册为作用域服务(Web API),请参阅下面的扩展方法.
public static IServiceCollection RegisterLogicServices(
this IServiceCollection services)
{
services.AddScoped<IServiceManagement, ServiceManagement>();
//generic services like UnitOfWork for E.F. Core 等.
services.AddScoped<IServiceA , ServiceA>();
services.AddScoped<IServiceB , ServiceB>();
services.AddScoped<IServiceC , ServiceC>();
return services;
}
例如,为了在控制器级别使用IServiceManagement
,我将IServiceManagement
作为构造函数参数注入,允许我访问服务的所有公开方法,如下所示:
public DoSomethingController(IServiceManagement manager)
{
_manager = manager
}
public IActionResult ExecuteSomething()
{
_manager.AdminService.DoSomething();
return Ok();
}
在这一点上,一切都运行得很好.
然而,我想知道的是,是否有可能在IAdminService
中有IServiceManagement
的范围,所以我想在IAdminService
到IServiceManagement
中执行一些在IEmailService
中的东西.
我可以想到的一种方法是使用IServiceProvider
,并将provider.GetRequiredService<IServiceManagement>()
作为构造函数的属性传入,如下所示
public ServiceManagement (
IServiceA ServiceA,
IServiceB ServiceB,
IserviceC serviceC,
IServiceProvider provider,
...)
{
_adminService = new Lazy<IAdminService>(
() => new AdminService(
ServiceA,
provider.GetRequiredService<IServiceManagement>()));
_emailService = new Lazy<IEmailService>(() => new EmailService(...));
_billService= new Lazy<IBillService>(() => new BillService(...));
}
我会对所有服务都这样做,因为可能会出现这样的情况:IAdminService
调用IEmailService
中的方法,IEmailService
中的相同方法可能调用IBillService
中的方法,依此类推.
我想知道的是,此用例使用IServiceProvider
是一个有效的用例,例如,
- 它在依赖项注入的上下文中有效吗?
- 当我访问从
IServiceProvider
开始的任何内容时会遇到问题吗? - 如果调用树太大(或者因为它的作用域应该很好),这是否会导致性能下降?
- 等.
让我们来看看极端的情况,假设我向后台服务注入了IServiceManagment
,这会导致任何问题吗?
如果你有其他解决方案可以解决我的担忧,请提出来,我想尽可能多地了解它.