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

  • 相关阅读:
    人脸识别常用的性能评价指标
    【计算机视觉】seetaFace
    【error】'isnan' was not declared in this scope
    【opencv基础】图像的几何变换
    [c++]base64编解码 and image
    【leetcode】232-Implement Queue using Stacks
    【leetcode】231-power-of-two
    C++中vector容器的常用操作方法实例总结
    【leetcode】226-invert-binary-tree
    第3章 文件I/O(2)_文件I/O系统调用及文件描述符
  • 原文地址:https://www.cnblogs.com/louiszh/p/14115826.html
Copyright © 2011-2022 走看看