在 ASP.NET Web 服务中,我有普通的依赖项,例如
services.AddScoped<IEmailService, EmailService>();
services.AddTransient<ICustomerCreationService, CustomerCreationService>();
services.AddTransient<ICustomerValidationService, CustomerValidationService>();
services.AddTransient<ICustomerService, CustomerService>();
services.AddTransient<IBackgroundService, BackgroundService>();
...
但是我们只有一些特殊的情况,只有在特定的情况下我们才需要上述情况的例外,所以我必须执行以下操作。在这个例子中,我想每次在BackgroundService的上下文中需要一个新的IEmailService时使用一个新的实例,而不是使用上面注册的“默认”Scoped实例,所以我需要执行以下操作:
services.AddTransient<BackgroundService>(sp =>
ActivatorUtilities.CreateInstance<ICustomerService>(sp,
ActivatorUtilities.CreateInstance<ICustomerValidationService>(sp,
ActivatorUtilities.CreateInstance<ICustomerCreationService>(sp,
// this is the only override we actually need (don't use scoped IEmailService)
ActivatorUtilities.CreateInstance<EmailService>(sp)
)
)
)
);
现在这里 ICustomerService 不需要自己激活;我只是希望它使用上面注册的普通依赖注入。 ICustomerCreationService 和 ICustomerValidationService 也是如此。但我认为我必须使用 ActivatorUtilities 为特殊依赖项的整个树指定参数,对吧?有更优雅的方式吗?我很想在上面说这样的话,但我看不出有什么办法。我错过了吗?
services.AddTransient<IBackgroundService>(sp =>
ActivatorUtilities.CreateInstanceAtAnyLevel<EmailService>(sp) // I wish...
);
我不确定,但这也许可以帮助你。 https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-8.0&tabs=visual-studio
public sealed class BackgroundService: IHostedService, IDisposable
{
public BackgroundService(IServiceScopeFactory serviceScopeFactory)
{
serviceScope = serviceScopeFactory.CreateScope();
}
public Task StartAsync(CancellationToken cancellationToken)
{
var services = serviceScope.ServiceProvider;
var emailService = services.GetRequiredService<IEmailService>();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
public void Dispose()
{
serviceScope.Dispose();
}
}