.NET Core開發實戰(第5課:依賴注入:良好架構的起點)--學習筆記(上)


05 | 依賴注入:良好架構的起點

為什么要使用依賴注入框架

  • 借助依賴注入框架,我們可以輕松管理類之間的依賴,幫助我們在構建應用時遵循設計原則,確保代碼的可維護性和可擴展性
  • ASP.NET Core 的整個架構中,依賴注入框架提供了對象創建和生命周期管理的核心能力,各個組件相互協作,也是由依賴注入框架的能力來實現的

組件包

  • Microsoft.Extensions.DependencyInjection.Abstractions
  • Microsoft.Extensions.DependencyInjection

依賴注入的核心是以上兩個組件包,一個是抽象包,一個是具體的實現

這里用到了一個經典的設計模式,接口實現分離模式

組件只需要依賴抽象接口,而不需要依賴具體實現,當使用的時候注入它的具體實現即可

這樣做的好處是可以在使用時決定具體的實現,也就意味着未來可以做任意的擴展,替換依賴注入框架的具體實現

默認情況下,使用 .NET Core 提供的內置依賴注入框架,也可以使用第三方的依賴注入框架來替換默認實現

核心類型

  • IServiceCollection:服務的注冊
  • ServiceDescriptor:每一個服務注冊時的信息
  • IServiceProvider:具體的容器,由 ServiceCollection Build 產生
  • IServiceScope:一個容器的子容器的生命周期

生命周期

  • 單例 Singleton:在整個根容器的生命周期內,都是單例,不管是子容器還是根容器,與作用域的區別是:一個是全局的,一個是范圍的單例
  • 作用域 Scoped:在 Scope 的生存周期內,也就是容器的生存周期內,或者子容器的生存周期內,如果我的容器釋放掉,我的對象也會釋放掉
  • 瞬時(暫時)Transient:每一次從容器里面獲取對象時,都可以得到一個全新的對象

新建一個 ASP.NET Core Web 應用程序 DependencyInjectionDemo,選擇API

添加一個 Services 文件夾,新建三個服務代表三個生命周期的服務

namespace DependencyInjectionDemo.Services
{
    public interface IMyScopedService { }
    public class MyScopedService : IMyScopedService
    {
    }
}
namespace DependencyInjectionDemo.Services
{
    public interface IMySingletonService { }
    public class MySingletonService : IMySingletonService
    {
    }
}
namespace DependencyInjectionDemo.Services
{
    public interface IMyTransientService { }
    public class MyTransientService : IMyTransientService
    {
    }
}

在 Startup 中注冊服務

public void ConfigureServices(IServiceCollection services)
{
    #region 注冊服務不同生命周期的服務

    // 將單例的服務注冊為單例的模式
    services.AddSingleton<IMySingletonService, MySingletonService>();

    // Scoped 的服務注冊為 Scoped 的生命周期
    services.AddScoped<IMyScopedService, MyScopedService>();

    // 瞬時的服務注冊為瞬時的生命周期
    services.AddTransient<IMyTransientService, MyTransientService>();

    #endregion

    services.AddControllers();
}

在 Controller 里面獲取我們的服務

// FromServices 標注的作用是從容器里面獲取我們的對象
// 每個對象獲取兩遍,用於對比每個生命周期獲取的對象是什么樣子的
// HashCode 代表對象的唯一性
[HttpGet]
public int GetService(
    [FromServices]IMySingletonService singleton1,
    [FromServices]IMySingletonService singleton2,
    [FromServices]IMyTransientService transient1,
    [FromServices]IMyTransientService transient2,
    [FromServices]IMyScopedService scoped1,
    [FromServices]IMyScopedService scoped2)
{
    Console.WriteLine($"singleton1:{singleton1.GetHashCode()}");
    Console.WriteLine($"singleton2:{singleton2.GetHashCode()}");
    Console.WriteLine($"transient1:{transient1.GetHashCode()}");
    Console.WriteLine($"transient2:{transient2.GetHashCode()}");
    Console.WriteLine($"scoped1:{scoped1.GetHashCode()}");
    Console.WriteLine($"scoped2:{scoped2.GetHashCode()}");
    Console.WriteLine($"========請求結束========");
    return 1;
}

注釋 Get 方法

//[HttpGet]
//public IEnumerable<WeatherForecast> Get()
//{
//    var rng = new Random();
//    return Enumerable.Range(1, 5).Select(index => new WeatherForecast
//    {
//        Date = DateTime.Now.AddDays(index),
//        TemperatureC = rng.Next(-20, 55),
//        Summary = Summaries[rng.Next(Summaries.Length)]
//    })
//    .ToArray();
//}

啟動程序,刷新瀏覽器再次訪問接口,輸出如下:

單例模式兩次的 HashCode 沒有變化

兩個瞬時服務兩次的 HashCode 完全不同,意味着瞬時服務每次請求都會得到一個新對象

范圍服務每個請求內是相同的,不同的請求之間得到的對象實例是不同的

GitHub源碼鏈接:

https://github.com/MINGSON666/Personal-Learning-Library/tree/main/DotNetCoreDevelopmentActualCombat/DependencyInjectionDemo

知識共享許可協議

本作品采用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議進行許可。

歡迎轉載、使用、重新發布,但務必保留文章署名 鄭子銘 (包含鏈接: http://www.cnblogs.com/MingsonZheng/ ),不得用於商業目的,基於本文修改后的作品務必以相同的許可發布。

如有任何疑問,請與我聯系 (MingsonZheng@outlook.com) 。


免責聲明!

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



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