zoukankan      html  css  js  c++  java
  • .NET Core 对象( Transient、Scope、Singleton )生命周期详解 (对象创建以及释放)

    首先我们在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 => 每次请求都会创建一个新的实例
    可以看到子容器childProvider1Account对象被创建了两次,因为可以看出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  ");
            }
    View Code

    测试结果

    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容器后再释放的;

  • 相关阅读:
    2017-2018-2 20165315 实验三《敏捷开发与XP实践》实验报告
    20165315 第九周学习总结
    20165315 结对编程练习_四则运算(整体总结)
    20165315 第八周学习总结
    2017-2018-2 20165315 实验二《Java面向对象程序设计》实验报告
    20165315 结对编程练习_四则运算(阶段总结)
    20165315 第七周学习总结
    2018-2019-1 《信息安全系统设计基础》实验一:开发环境的熟悉--实验报告
    2018-2019-1 20165225《信息安全系统设计基础》第三周学习总结
    20165225 实验一:缓冲区溢出漏洞实验
  • 原文地址:https://www.cnblogs.com/louiszh/p/14115826.html
Copyright © 2011-2022 走看看