【发布时间】:2021-06-07 17:03:58
【问题描述】:
我想在其他临时服务之间共享一项服务。现在它不是真正的服务,但在现实生活中的应用程序中它会。如何使用依赖注入共享我的服务?
我在下面添加了一些演示代码。 SharedService 应该是 MyCreatorService 的“范围”中 MyTransientService1 和 MyTransientService2 的同一个对象。
第二个断言失败,而这是我想要完成的。
class Program
{
static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
private static IHostBuilder CreateHostBuilder(string[] args)
=> Host.CreateDefaultBuilder(args)
.ConfigureServices((_, services) =>
{
services.AddScoped<SharedService>();
services.AddTransient<MyTransientService1>();
services.AddTransient<MyTransientService2>();
services.AddTransient<MyCreatorService>();
services.AddHostedService<MyHostedService>();
});
}
public class SharedService
{
public Guid Id { get; set; }
}
public class MyTransientService1
{
public SharedService Shared;
public MyTransientService1(SharedService shared)
{
Shared = shared;
}
}
public class MyTransientService2
{
public SharedService Shared;
public MyTransientService2(SharedService shared)
{
Shared = shared;
}
}
public class MyCreatorService
{
public MyTransientService1 Service1;
public MyTransientService2 Service2;
public MyCreatorService(MyTransientService1 s1, MyTransientService2 s2)
{
Service1 = s1;
Service2 = s2;
}
}
public class MyHostedService : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
public MyHostedService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
var creator1 = _serviceProvider.GetRequiredService<MyCreatorService>();
var creator2 = _serviceProvider.GetRequiredService<MyCreatorService>();
Assert.That(creator1.Service1.Shared.Id, Is.EqualTo(creator1.Service2.Shared.Id));
Assert.That(creator1.Service1.Shared.Id, Is.Not.EqualTo(creator2.Service1.Shared.Id));
return Task.CompletedTask;
}
}
【问题讨论】:
-
您要求解决方案,您的问题中似乎已经提供了该解决方案。你能解释一下这个设置有什么问题吗?
-
@Silvermind:第二个断言失败,这就是我想要完成的。我想创建以某种范围方式共享另一个服务的服务。例如,MyHostedService 创建两个 MyCreatorService。 MyCreatorService 有两个临时服务,它们应该共享一个公共服务。但是这个公共服务对于 MyCreatorService 来说是独一无二的。希望这是有道理的。
-
使用 MS.DI,如果您从根范围解析 Scoped 依赖项,则该 Scoped 将有效地成为单例。这就是您的托管服务中发生的情况。托管服务实际上是一个单例(即使您可能将其注册为瞬态,这并不重要),它的
IServiceProvider是根提供者。这就是导致您的问题的原因。解决方案是在托管服务的方法中使用serviceProvider.CreateScope()启动一个新范围。