先複習一下
ServiceDescriptor
=> 描述服務如何以及對應實體取得的物件IServiceCollection
=> ServiceDescriptor
的集合IServiceProvider
=> 服務實際的提供者我們前面提到了在.Net Core 中 Lifetime 被註冊為 Scoped
在每個Request 中會拿到相同的Instance
那要怎麼做到這件事呢,就需要有一個控制生命週期的物件IServiceScope
每個 IServiceScope
中會有一個 IServiceProvider
, IServiceScope
會負責管理自己所有 IServiceProvider
的生命週期。
這邊來看個圖吧
.Net Core的應用程式啟動後會生成一個IServicePovider
,後面姑且稱呼他為Root
可以看見每個Request都會建立一個IServiceScope
可以透過IServiceProvider.CreateScope
來產生一個IServiceScope
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<ISingletonService, SingletonService>();
serviceCollection.AddScoped<IScopedService, ScopedService>();
serviceCollection.AddTransient<ITransientService, TransientService>();
var serviceProvider = serviceCollection.BuildServiceProvider();
IServiceScope serviceScope = serviceProvider.CreateScope();
有了Scope的概念之後,我們來看看生命週期是如何管理的吧
IServiceProver
在解析完服務並取出執行個體,會將服務放在一個名為RealizedServices
的ConcurrentDictionary
,當這個服務實作了IDispose
或 IAsyncDisposable
時他會被另外加到Disposable Services
的清單中。
public interface IService{}
public class Service : IService{}
public interface IDisposableService{}
public class DisposableService : IDisposableService, IDisposable
{
public void Dispose()
{
}
}
當我們解析或注入時,執行個體會被放到對應的清單
而當 IServiceScope
的實例被Dispose的時候,會呼叫ServiceProvider
的Dispose()
方法,並依序呼叫Disposable Services
中的Instance的Dispose()
我們回過頭來看當我們要求/注入三種不同生命週期時服務是怎麼被處裡的
如果Root
的RealizedServices
中有對應的執行個體,那就會取該執行個體。沒有的話就新增一個執行個體並放到Root
的RealizedServices
,有實現IDisposable
,會另外再放到Disposable Services
如果當前Scope的IServiceProvider的RealizedServices
中有對應的執行個體,那就會取該執行個體。沒有的話就新增一個執行個體並放到
當前Scope的IServiceProvider的RealizedServices
,有實現IDisposable
,會另外再放到Disposable Services
)
管他有沒有,新增一個執行個體就對了
program.cs
var serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<ISingletonService, SingletonService>();
serviceCollection.AddScoped<IScopedService, ScopedService>();
serviceCollection.AddTransient<ITransientService, TransientService>();
var root = serviceCollection.BuildServiceProvider();
var childScope = root.CreateScope();
var childProvider = childScope.ServiceProvider;
var descendantScope = childProvider.CreateScope();
var descendantProvider = descendantScope.ServiceProvider;
var descendantSingletonService = descendantProvider.GetService<ISingletonService>();
var descendantScopedService = descendantProvider.GetService<IScopedService>();
var childSingletonService = childProvider.GetService<ISingletonService>();
var childScopedService = childProvider.GetService<IScopedService>();
var rootSingletonService = root.GetService<ISingletonService>();
var rootScopedService = root.GetService<IScopedService>();
Console.WriteLine("Root Singleton Service: " + rootSingletonService.Id);
Console.WriteLine("Root Scoped Service: " + rootScopedService.Id);
Console.WriteLine("Child Singleton Service: " + childSingletonService.Id);
Console.WriteLine("Child Scoped Service: " + childScopedService.Id);
Console.WriteLine("Descendant Singleton Service: " + descendantSingletonService.Id);
Console.WriteLine("Descendant Scoped Service: " + descendantScopedService.Id);
結構圖:
執行結果:
可以看見所有的SingletonService
都是同一個,不同Scope的ScopeService
是不同的
先發文我慢慢補 0.0b
補在[Day9] 補坑之談談 .Net core 的相依性注入實作