在ASP.NET Core中的托管服务中使用作用域服务



我有一个服务,我想在其他临时服务之间共享。现在,它并不是一项真正的服务,但在现实生活中,它会的。如何使用依赖项注入共享我的服务?

我在下面添加了一些演示代码。SharedService应该是"中的MyTransientService1和MyTransientService 2的相同对象;"范围";MyCreatorService。

第二个断言失败,而这正是我想要实现的。

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;
}
}

如果使用AddScoped,则实例将与请求中的相同(例如HTTP请求和响应(。如果您需要在每次解决其他服务时创建这些服务,那么您确实可以使用AddTransient,但除此之外,您也可以使用AddScoped

我还建议您以这种方式绑定MyHostedService(如果它与您描述的问题有关(,因为它似乎提供了Singleton绑定。如果外部服务(具有注入依赖项的服务(的范围较窄,则将劫持注入依赖项。因此,具有瞬态依赖关系的单例服务将使其所有依赖关系成为单例服务,因为外部服务只创建一次,其依赖关系只解析一次。

更新

在更清楚地了解问题后,这应该对您有效(不需要其他绑定(:

services.AddTransient<MyCreatorService>(_ =>
{
var shared = new SharedService();
shared.Id = Guid.NewGuid();
return new MyCreatorService(
new MyTransientService1(shared),
new MyTransientService2(shared));
});
  1. SharedService类添加构造函数,否则Id始终为000

  2. 使用以下代码创建不同的作用域,因此SharedService将被初始化两次:

    MyCreatorService creator1;
    MyCreatorService creator2;
    using (var scope1 = _serviceProvider.CreateScope())
    {
    creator1 = scope1.ServiceProvider.GetRequiredService<MyCreatorService>();
    }
    using (var scope2 = _serviceProvider.CreateScope())
    {
    creator2 = scope2.ServiceProvider.GetRequiredService<MyCreatorService>();
    }
    

最新更新