.NET Core 对象( Transient、Scope、Singleton )生命周期详解 (对象创建以及释放)
2024-09-02 16:04:04
首先我们在VS2019中创建一个.NET Core的控制台程序,方便演示;
需要安装两个依赖包
Microsoft.Extensions.DependencyInjection 依赖注入对象的具体实现
Microsoft.Extensions.DependencyInjection.Abstractions 依赖注入对象的抽象
Part 1 : AddTransient AddScoped AddSingleton
话不多说,看以下Demo的代码以及运行结果
public static class Demo
{
public interface IAccount { }
public interface IMessage { }
public interface ITool { }
public class Base
{
public Base()
{
Console.WriteLine($"{GetType().Name} Created");
}
}
public class Account : Base,IAccount { }
public class Message : Base, IMessage { }
public class Tool : Base, ITool { } public static void Run()
{
Console.WriteLine("Run Method Begin...");
//root provider
var rootProvider = new ServiceCollection()
.AddTransient<IAccount, Account>()
.AddScoped<IMessage, Message>()
.AddSingleton<ITool, Tool>()
.BuildServiceProvider();
//create child provider
var childProvider1 = rootProvider.CreateScope().ServiceProvider;
var childProvider2 = rootProvider.CreateScope().ServiceProvider; GetService<IAccount>(childProvider1);
GetService<IMessage>(childProvider1);
GetService<ITool>(childProvider1);
Console.WriteLine();
GetService<IAccount>(childProvider2);
GetService<IMessage>(childProvider2);
GetService<ITool>(childProvider2);
Console.WriteLine("Run Method End..."); } public static void GetService<T>(IServiceProvider serviceProvider)
{
serviceProvider.GetService<T>();
serviceProvider.GetService<T>();
} }
调用Demo.Run() 输出结果
Run Method Begin...
Account Created
Account Created
Message Created
Tool Created Account Created
Account Created
Message Created
Run Method End...
调用GetService<T>方法获取实例进行实例的创建,Account、Message、Tool都继承了Base类,因此在被创建时,会调用Base类的构造函数;
AddTransient => 每次请求都会创建一个新的实例
可以看到子容器childProvider1中 Account对象被创建了两次,因为可以看出AddTransient每次请求时都会创建一个新的实例;
AddScoped => 同一个请求中返回同一个实例
在子容器的作用域中进行查找,同一个子容器中只会创建一次;所以childProvider1中调用两次GetService()方法只创建一次实列;
childProvider2也只创建了一次Message
AddSingleton => 整个应用程序只会创建一次;单例永远从根容器rootProvider中查找
Tool 因为是Singleton 类型,因此整个程序中只创建了一次;
Part 2 : IDisposable
第二部分我们来看看创建的这些对象是何时进行释放的
在以上的代码中,将Base类实现IDisposable接口
public class Base : IDisposable
{
public Base()
{
Console.WriteLine($"{GetType().Name} Created");
} public void Dispose()
{
Console.WriteLine($"{GetType().Name} Disposed");
}
}
在Run方法中使用Using来测试结果:
public static void Run()
{
//root provider
using (ServiceProvider root = new ServiceCollection()
.AddTransient<IAccount, Account>()
.AddScoped<IMessage, Message>()
.AddSingleton<ITool, Tool>()
.BuildServiceProvider())
{
using (var scope = root.CreateScope())
{
var child = scope.ServiceProvider;
child.GetService<IAccount>();
child.GetService<IMessage>();
child.GetService<ITool>();
Console.WriteLine("Child provider begin dispose");
}
Console.WriteLine("Child provider disposed ");
Console.WriteLine("Root provider begin dispose "); }
Console.WriteLine("Root provider disposed ");
}
测试结果
Account Created
Message Created
Tool Created
Child provider begin dispose
Message Disposed
Account Disposed
Child provider disposed
Root provider begin dispose
Tool Disposed
Root provider disposed
可以看出 AddTransient 和 AddScoped 在使用完child容器后,就调用了Base的 Dispose() ;而 AddSingle则在使用完root容器后再释放的;
最新文章
- hadoop拾遗(一)---- 避免切分map文件
- XoftSpy 4.13的注册算法分析
- 静态Web开发 DOM
- python 中对list做减法操作
- KVO奥秘
- Spring IOC之依赖
- MyBatis 笔记总结
- JavaScript判断变量数据类型
- freemarker之list遍历(八)
- 温故而知新--hashtable
- java开发中几种常见的线程池
- UML在代码中的展现
- docker 笔记
- 【C#加深理解系列】(二)序列化
- Ruby数组(1):基本用法
- 学习Acegi应用到实际项目中(11)- 切换用户
- maven发布jar包到nexus
- 洛谷P4593 [TJOI2018]教科书般的亵渎(拉格朗日插值)
- jcmd
- HBase的Shell命令和JavaAPI