服务的生命周期,示例代码:
public class ServiceA : IServiceA, IDisposable
{
private readonly int _n;
public ServiceA(INumberService numberService)
{
_n = numberService.GetNumber();
Console.WriteLine($"ctor {nameof(ServiceA)}, {_n}");
}
public void A() => Console.WriteLine($"{nameof(A)}, {_n}");
public void Dispose() => Console.WriteLine($"disposing {nameof(ServiceA)}, {_n}");
}
public class ServiceB : IServiceB, IDisposable
{
private readonly int _n;
public ServiceB(INumberService numberService)
{
_n = numberService.GetNumber();
Console.WriteLine($"ctor {nameof(ServiceB)}, {_n}");
}
public void B() => Console.WriteLine($"{nameof(B)}, {_n}");
public void Dispose() => Console.WriteLine($"disposing {nameof(ServiceB)}, {_n}");
}
public class ServiceC : IServiceC, IDisposable
{
private bool _isDisposed = false;
private readonly int _n;
public ServiceC(INumberService numberService)
{
_n = numberService.GetNumber();
Console.WriteLine($"ctor {nameof(ServiceC)}, {_n}");
}
public void C()
{
if (_isDisposed)
throw new ObjectDisposedException("ServiceC");
Console.WriteLine($"{nameof(C)}, {_n}");
}
public void Dispose()
{
Console.WriteLine($"disposing {nameof(ServiceC)}, {_n}");
_isDisposed = true;
}
}
public class NumberService : INumberService
{
private int _number = 0;
public int GetNumber() => Interlocked.Increment(ref _number);
}
public class ControllerX : IDisposable
{
private readonly IServiceA _serviceA;
private readonly IServiceB _serviceB;
private readonly int _n;
private int _countm = 0;
public ControllerX(IServiceA serviceA, IServiceB serviceB, INumberService numberService)
{
_n = numberService.GetNumber();
Console.WriteLine($"ctor {nameof(ControllerX)}, {_n}");
_serviceA = serviceA;
_serviceB = serviceB;
}
public void M()
{
Console.WriteLine($"invoked {nameof(M)} for the {++_countm}. time");
_serviceA.A();
_serviceB.B();
}
public void Dispose() => Console.WriteLine($"disposing {nameof(ControllerX)}, {_n}");
}
public interface IServiceA
{
void A();
}
public interface IServiceB
{
void B();
}
public interface IServiceC
{
void C();
}
public interface INumberService
{
int GetNumber();
}
调用SingletonAndTransient()的输出
class Program
{
static void Main()
{
SingletonAndTransient();
}
private static void SingletonAndTransient()
{
Console.WriteLine(nameof(SingletonAndTransient));
ServiceProvider RegisterServices()
{
IServiceCollection services = new ServiceCollection();
services.AddSingleton<IServiceA, ServiceA>();
services.AddTransient<IServiceB, ServiceB>();
services.Add(new ServiceDescriptor(typeof(ControllerX), typeof(ControllerX), ServiceLifetime.Transient));
services.AddSingleton<INumberService, NumberService>();
return services.BuildServiceProvider();
}
using (ServiceProvider container = RegisterServices())
{
Console.WriteLine($"requesting {nameof(ControllerX)}");
ControllerX x = container.GetRequiredService<ControllerX>();
x.M();
x.M();
Console.WriteLine($"requesting {nameof(ControllerX)}");
ControllerX x2 = container.GetRequiredService<ControllerX>();
x2.M();
Console.WriteLine();
}
}
}
SingletonAndTransient
requesting ControllerX
ctor ServiceA, 1
ctor ServiceB, 2
ctor ControllerX, 3
invoked M for the 1. time
A, 1
B, 2
invoked M for the 2. time
A, 1
B, 2
requesting ControllerX
ctor ServiceB, 4
ctor ControllerX, 5
invoked M for the 1. time
A, 1
B, 4
disposing ControllerX, 5
disposing ServiceB, 4
disposing ControllerX, 3
disposing ServiceB, 2
disposing ServiceA, 1
UsingScoped()的输出
class Program
{
static void Main()
{
UsingScoped();
}
private static void UsingScoped()
{
Console.WriteLine(nameof(UsingScoped));
ServiceProvider RegisterServices()
{
var services = new ServiceCollection();
services.AddSingleton<INumberService, NumberService>();
services.AddScoped<IServiceA, ServiceA>();
services.AddSingleton<IServiceB, ServiceB>();
services.AddTransient<IServiceC, ServiceC>();
return services.BuildServiceProvider();
}
using (ServiceProvider container = RegisterServices())
{
using (IServiceScope scope1 = container.CreateScope())
{
IServiceA a1 = scope1.ServiceProvider.GetService<IServiceA>();
a1.A();
IServiceA a2 = scope1.ServiceProvider.GetService<IServiceA>();
a2.A();
IServiceB b1 = scope1.ServiceProvider.GetService<IServiceB>();
b1.B();
IServiceC c1 = scope1.ServiceProvider.GetService<IServiceC>();
c1.C();
IServiceC c2 = scope1.ServiceProvider.GetService<IServiceC>();
c2.C();
}
Console.WriteLine("end of scope1");
using (IServiceScope scope2 = container.CreateScope())
{
IServiceA a3 = scope2.ServiceProvider.GetService<IServiceA>();
a3.A();
IServiceB b2 = scope2.ServiceProvider.GetService<IServiceB>();
b2.B();
IServiceC c3 = scope2.ServiceProvider.GetService<IServiceC>();
c3.C();
}
Console.WriteLine("end of scope2");
Console.WriteLine();
}
}
}
UsingScoped
ctor ServiceA, 1
A, 1
A, 1
ctor ServiceB, 2
B, 2
ctor ServiceC, 3
C, 3
ctor ServiceC, 4
C, 4
disposing ServiceC, 4
disposing ServiceC, 3
disposing ServiceA, 1
end of scope1
ctor ServiceA, 5
A, 5
B, 2
ctor ServiceC, 6
C, 6
disposing ServiceC, 6
disposing ServiceA, 5
end of scope2
disposing ServiceB, 2
CustomFactories()的输出
class Program
{
static void Main()
{
CustomFactories();
}
private static void CustomFactories()
{
Console.WriteLine(nameof(CustomFactories));
IServiceB CreateServiceBFactory(IServiceProvider provider) =>
new ServiceB(provider.GetService<INumberService>());
ServiceProvider RegisterServices()
{
var numberService = new NumberService();
var services = new ServiceCollection();
services.AddSingleton<INumberService>(numberService);
services.AddTransient<IServiceB>(CreateServiceBFactory);
services.AddSingleton<IServiceA, ServiceA>();
return services.BuildServiceProvider();
}
using (ServiceProvider container = RegisterServices())
{
IServiceA a1 = container.GetService<IServiceA>();
IServiceA a2 = container.GetService<IServiceA>();
IServiceB b1 = container.GetService<IServiceB>();
IServiceB b2 = container.GetService<IServiceB>();
}
Console.WriteLine();
}
}
CustomFactories
ctor ServiceA, 1
ctor ServiceB, 2
ctor ServiceB, 3
disposing ServiceB, 3
disposing ServiceB, 2
disposing ServiceA, 1
服务的生命周期:
- 单例:总是返回相同实例
- 瞬态:每次注入服务时都会返回一个新对象。每次从容器中请求服务时,都会创建一个新实例
- Scoped: 总是从相同的作用域返回相同的实例,不同的作用域返回不同的实例
注册服务:
- AddSingleton和AddTransient都是ServiceCollection的扩展方法,更易于注册服务。还有一个更原始一点的Add方法,Add方法用起来更麻烦一点,并且是只有用IServiceCollection时才可以看到,用ServiceCollection的时候是看不到Add方法的
services.Add(new ServiceDescriptor(typeof(ControllerX), typeof(ControllerX), ServiceLifetime.Transient));
对于Scoped:
- ASP.NET Core Web应用程序中,默认作用域是一个HTTP web request。当从容器中请求一个Scoped服务的时候,如果这个请求是来自同一个HTTP Web request,则返回相同的实例。反之,返回不同的实例。这允许在HTTP Web request中轻松共享状态
- 对非ASP.NET Core web应用程序,需要自己创建作用域
服务的释放:
- 在作用域末尾,transient和scoped服务会被自动释放,但是singleton不会被释放
- 释放作用域时,释放transient服务和scoped服务。释放根提供程序时,释放singleton服务
- 不需要在服务上调用Dispose来释放它们。只要实现了IDisposable接口,容器会自动调用Dispose方法
- .NET Core 2.0 按照创建的相反顺序来释放服务
其他实例化方法:
IServiceB CreateServiceBFactory(IServiceProvider provider) =>
new ServiceB(provider.GetService<INumberService>());
services.AddTransient<IServiceB>(CreateServiceBFactory);
var numberService = new NumberService();
services.AddSingleton<INumberService>(numberService);