重新整理 .net core 實踐篇————依賴注入應用之生命法則[三]

不問前世發表於2021-05-27

前言

該章演示依賴注入中,物件的釋放行為。

緊接上文表示,演示:

services.AddSingleton<IMySingletonService, MySingletonService>();
services.AddSingleton<IMySingletonService>(new MySingletonService());
services.AddSingleton<IMySingletonService>(ServiceProvider =>
{
	return new MySingletonService();
});

這三種生命週期的注入方式的不同,他們的生命週期不同。

主要是兩條法則:

  1. DI 只負責釋放由其建立的物件例項,DI 在容器或者子容器釋放時,釋放由其建立的物件的例項。

  2. 不要在根容器中獲取瞬時服務,不要在根容器中獲取瞬時服務,不要在根容器中獲取瞬時服務,重要的事情說三遍。

正文

第一條法則證明公理:

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 還是比較重要的,一般大一點的專案都會用上,比較方便吧。

上述只是個人整理,如果錯誤,望請指教。

相關文章