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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM