在 ASP.NET Core 中的托管服务中使用 Scoped 服务
Using Scoped services within a hosted service in ASP.NET Core
我有一个服务想在其他临时服务之间共享。现在它不是真正的服务,但在现实生活中它会。我将如何使用依赖注入来共享我的服务?
我在下面添加了一些演示代码。 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;
}
}
如果您使用 AddScoped
,实例将与请求中的实例相同(例如对于 HTTP 请求和响应)。如果您需要在每次解析时创建您的其他服务,您确实可以使用 AddTransient
,否则您也可以使用 AddScoped
.
我还建议您以这种方式绑定 MyHostedService
(如果它与您描述的问题有任何关系),因为它似乎提供了 。如果 outer 服务(具有注入依赖项的服务)的范围较窄,它将 hold 人质 注入依赖项。因此,具有瞬态依赖项的单例服务将使其所有依赖项成为单例,因为外部服务只会创建一次并且其依赖项只会被解析一次。
更新
在更清楚地理解问题之后,这应该对你有用(不需要其他绑定):
services.AddTransient<MyCreatorService>(_ =>
{
var shared = new SharedService();
shared.Id = Guid.NewGuid();
return new MyCreatorService(
new MyTransientService1(shared),
new MyTransientService2(shared));
});
我有一个服务想在其他临时服务之间共享。现在它不是真正的服务,但在现实生活中它会。我将如何使用依赖注入来共享我的服务?
我在下面添加了一些演示代码。 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;
}
}
如果您使用 AddScoped
,实例将与请求中的实例相同(例如对于 HTTP 请求和响应)。如果您需要在每次解析时创建您的其他服务,您确实可以使用 AddTransient
,否则您也可以使用 AddScoped
.
我还建议您以这种方式绑定 MyHostedService
(如果它与您描述的问题有任何关系),因为它似乎提供了
更新
在更清楚地理解问题之后,这应该对你有用(不需要其他绑定):
services.AddTransient<MyCreatorService>(_ =>
{
var shared = new SharedService();
shared.Id = Guid.NewGuid();
return new MyCreatorService(
new MyTransientService1(shared),
new MyTransientService2(shared));
});