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

  • 相关阅读:
    VS2010制作网站自定义安装程序 转
    SQL Express几个版本的区别
    WebGIS(PostgreSQL+GeoServer+OpenLayers)之二 GeoServer安装与数据配置
    CentOS设置ipv4和ipv6
    Linux下Vim的启动与退出
    Linux字符界面基本操作
    CentOS字符界面与图形界面的切换
    mysql显示SQL语句执行时间
    将shp文件导入到mysql数据库中
    MySQL导入sql 文件的5大步骤
  • 原文地址:https://www.cnblogs.com/louiszh/p/14115826.html
Copyright © 2020-2023  润新知