提问者:小点点

在. net 5中使用工厂方法进行依赖注入的对象生命周期


我在玩. net 5依赖注入,这非常有用。从各种来源,就像这个问题的公认答案依赖注入,用参数注入,我了解到使用Add瞬态/Scoped/Singleton中的工厂方法,容器不会处置创建的对象,即使对象实现了IDisposable。但下面的代码清楚地告诉我,对象是自动处置的(这很棒,但我想了解背后的故事)。

using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace ConsoleDI.Example
{
    public class TransientDisposable : IDisposable
    {
        public void Dispose() => Console.WriteLine($"{nameof(TransientDisposable)}.Dispose()");
    }

    public class ScopedDisposable : IDisposable
    {
        public void Dispose() => Console.WriteLine($"{nameof(ScopedDisposable)}.Dispose()");
    }

    public class SingletonDisposable : IDisposable
    {
        public void Dispose() => Console.WriteLine($"{nameof(SingletonDisposable)}.Dispose()");
    }

    class Program
    {
        static void Main(string[] args)
        {
            using IHost host = CreateHostBuilder(args).Build();

            ExemplifyDisposableScoping(host.Services, "Scope 1");
            Console.WriteLine();

            ExemplifyDisposableScoping(host.Services, "Scope 2");
            Console.WriteLine();

            host.Run();
        }

        static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((_, services) =>
                    services.AddTransient<TransientDisposable>(_ => new TransientDisposable())
                            .AddScoped<ScopedDisposable>(_ => new ScopedDisposable())
                            .AddSingleton<SingletonDisposable>(_ => new SingletonDisposable())
                );

        static void ExemplifyDisposableScoping(IServiceProvider services, string scope)
        {
            Console.WriteLine($"{scope}...");

            using IServiceScope serviceScope = services.CreateScope();
            IServiceProvider provider = serviceScope.ServiceProvider;

            _ = provider.GetRequiredService<TransientDisposable>();
            _ = provider.GetRequiredService<ScopedDisposable>();
            _ = provider.GetRequiredService<SingletonDisposable>();
        }
    }
}

输出:

Scope 1...
ScopedDisposable.Dispose()
TransientDisposable.Dispose()

Scope 2...
ScopedDisposable.Dispose()
TransientDisposable.Dispose()

info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /home/zhjun/Work/tmp/ConsoleDI.Example
^Cinfo: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
SingletonDisposable.Dispose()

这是为什么呢?这是. net 5DI容器的改进吗?还是总是这样?


共1个答案

匿名用户

我不会说选择的答案不正确,但至少它是不完整的,因为唯一不会导致实例被处置的注册是AddSingleton

在以下示例中,服务由服务容器创建并自动配置:

services.AddScoped<Service1>();
services.AddSingleton<Service2>();
services.AddSingleton<IService3>(sp => new Service3());

在以下示例中:[…]框架不会自动处置服务。

services.AddSingleton<Service1>(new Service1());
services.AddSingleton(new Service2());

这背后的中心思想是使用AddSingleton