前言
該章演示依賴注入中,物件的釋放行為。
緊接上文表示,演示:
services.AddSingleton<IMySingletonService, MySingletonService>();
services.AddSingleton<IMySingletonService>(new MySingletonService());
services.AddSingleton<IMySingletonService>(ServiceProvider =>
{
return new MySingletonService();
});
這三種生命週期的注入方式的不同,他們的生命週期不同。
主要是兩條法則:
-
DI 只負責釋放由其建立的物件例項,DI 在容器或者子容器釋放時,釋放由其建立的物件的例項。
-
不要在根容器中獲取瞬時服務,不要在根容器中獲取瞬時服務,不要在根容器中獲取瞬時服務,重要的事情說三遍。
正文
第一條法則證明公理:
public interface ITestService
{
}
public class TestService:ITestService,IDisposable
{
public void Dispose()
{
Console.WriteLine($"DisposableTestService Disposed:{this.GetHashCode()}");
}
}
註冊:
services.AddSingleton<ITestService>(new TestService());
然後測試:
[HttpGet]
public int GetService([FromServices] ITestService testService,[FromServices]IHostApplicationLifetime hostApplicationLifetime,[FromQuery]bool stop = false)
{
if (stop)
{
hostApplicationLifetime.StopApplication();
}
return 1;
}
結果:
應用離開的時候並沒有呼叫我們的Dispose方式。
那麼換一種註冊方式:
services.AddSingleton<ITestService, TestService>();
結果如下:
應用程式離開的時候會呼叫我們的dispose。
再換一種方式:
services.AddSingleton<ITestService>(serviceProvider =>
{
return new TestService();
});
也會主動呼叫這個dispose。
證明不要在根容器中獲取瞬時服務:
理論上離開區域那麼應該會呼叫dispose 釋放,但是情況和我們想的不一樣。
測試程式碼:
[HttpGet]
public int GetService([FromServices]IHostApplicationLifetime hostApplicationLifetime,[FromQuery]bool stop = false)
{
if (stop)
{
hostApplicationLifetime.StopApplication();
}
return 1;
}
當訪問stop引數不為true
當訪問stop引數為true,也就是關閉服務的時候:
說明根容器獲取的瞬時物件,並沒有在離開區域內釋放,而是在容器回收的時候才釋放。間接的說明一個問題,這個物件起碼被我們的根容器間接引用了,這裡埋個坑,後面系列解釋為什麼。
那麼為什麼我們從FromServices中獲取的ITestService會被釋放呢?
這是應為,其實每一次http訪問都會建立一個子容器來保證隔離:
[HttpGet]
public int GetService([FromServices]IHostApplicationLifetime hostApplicationLifetime,[FromQuery]bool stop = false)
{
using (IServiceScope scope = HttpContext.RequestServices.CreateScope())
{
var obj=scope.ServiceProvider.GetService<ITestService>();
}
if (stop)
{
hostApplicationLifetime.StopApplication();
}
return 1;
}
結果:
結
下一節介紹Autofac,主要介紹一下什麼情況我們需要使用第三方的Autofac,它給我們帶來什麼東西,或者給我們帶來什麼方便,以及如何操作。Autofac 還是比較重要的,一般大一點的專案都會用上,比較方便吧。
上述只是個人整理,如果錯誤,望請指教。