在 ASP.NET Core 中的托管服务中使用范围服务

Arn*_*eek 5 c# dependency-injection

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

我在下面添加了一些演示代码。对于 MyCreatorService 的“范围”中的 MyTransientService1 和 MyTransientService2,SharedService 应该是相同的对象。

第二个断言失败了,而这是我想要完成的。

    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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

Aag*_*age 1

如果您使用,则请求中的AddScoped实例将相同(例如 HTTP 请求和响应)。如果您需要每次解析其他服务时都创建它们,那么您确实可以使用,但除此之外您也可以使用。AddTransientAddScoped

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

更新

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

services.AddTransient<MyCreatorService>(_ =>
            {
                var shared = new SharedService();
                shared.Id = Guid.NewGuid();
                return new MyCreatorService(
                    new MyTransientService1(shared),
                    new MyTransientService2(shared));
            });

Run Code Online (Sandbox Code Playgroud)