我在玩. 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容器的改进吗?还是总是这样?
我不会说选择的答案不正确,但至少它是不完整的,因为唯一不会导致实例被处置的注册是AddSingleton
在以下示例中,服务由服务容器创建并自动配置:
services.AddScoped<Service1>();
services.AddSingleton<Service2>();
services.AddSingleton<IService3>(sp => new Service3());
在以下示例中:[…]框架不会自动处置服务。
services.AddSingleton<Service1>(new Service1());
services.AddSingleton(new Service2());
这背后的中心思想是使用AddSingleton