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