重新整理 .net core 实践篇————依赖注入应用之生命法则[三]

前言

该章演示依赖注入中,对象的释放行为。

紧接上文表示,演示:

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 还是比较重要的,一般大一点的项目都会用上,比较方便吧。

上述只是个人整理,如果错误,望请指教。