重新整理 .net core 实践篇————依赖注入应用之生命法则[三]
前言
该章演示依赖注入中,对象的释放行为。
紧接上文表示,演示:
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 还是比较重要的,一般大一点的项目都会用上,比较方便吧。
上述只是个人整理,如果错误,望请指教。