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


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

除了使用泛型的方式注冊服務之外,還有其他的方式

添加一個 OrderService

public interface IOrderService
{

}

public class OrderService : IOrderService
{

}


public class OrderServiceEx : IOrderService
{

}

在 Startup 中注冊服務

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

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

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

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

    #endregion

    #region 花式注冊

    services.AddSingleton<IOrderService>(new OrderService());  //直接注入實例

    //// 通過工廠模式
    //services.AddSingleton<IOrderService>(serviceProvider =>
    //{
    //    return new OrderServiceEx();
    //});

    //services.AddScoped<IOrderService>(serviceProvider =>
    //{
    //    // 可以使用 IServiceProvider 入參,也就意味着可以從容器里面獲取多個對象,進行組裝,得到最終的實現實例
    //    // 也就是可以把工廠類設計的比較復雜,比如說實現類依賴了容器里面的另外一個類,或者用另一個類來包裝原有的實現
    //    //serviceProvider.GetService<>()

    //    return new OrderServiceEx();
    //});

    #endregion

    #region 嘗試注冊(如果服務已經注冊過,則不再注冊)

    services.TryAddSingleton<IOrderService, OrderServiceEx>();

    #endregion

    services.AddControllers();
}

在服務端 WeatherForecastController 定義另外一個接口

// IEnumerable<IOrderService>:獲取曾經注冊過的所有 IOrderService
public int GetServiceList([FromServices]IEnumerable<IOrderService> services)
{
    foreach (var item in services)
    {
        Console.WriteLine($"獲取到服務實例:{item.ToString()}:{item.GetHashCode()}");
    }
    return 1;
}

調整一下程序的啟動頁面,Properties 下的 launchSetting.json 的這一行代碼

"launchUrl": "weatherforecast/getservicelist",

啟動程序,輸出如下:

獲取到服務實例:DependencyInjectionDemo.Services.OrderService:25560520

只有一個實例,說明 TryAddSingleton 沒有生效

接着,注冊兩個服務

services.AddSingleton<IOrderService>(new OrderService());
services.AddSingleton<IOrderService, OrderServiceEx>();

啟動程序,輸出如下:

獲取到服務實例:DependencyInjectionDemo.Services.OrderService:16991442
獲取到服務實例:DependencyInjectionDemo.Services.OrderServiceEx:25560520

結果獲取到了兩個實例

接下來,了解一下 TryAddEnumerable 與 TryAddSingleton 的區別

#region 嘗試注冊(如果服務已經注冊過,則不再注冊)

services.TryAddSingleton<IOrderService, OrderServiceEx>();// 接口類型重復,則不注冊

services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService, OrderService>());// 相同類型的接口,實現類相同,則不注冊

#endregion

注冊服務

services.AddSingleton<IOrderService>(new OrderService());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService, OrderService>());

啟動程序,輸出如下:

獲取到服務實例:DependencyInjectionDemo.Services.OrderService:53046438

因為已經注冊過 OrderService,所以第二句代碼不生效

以不同的實現注冊服務

services.AddSingleton<IOrderService>(new OrderService());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService, OrderServiceEx>());

啟動程序,輸出如下:

獲取到服務實例:DependencyInjectionDemo.Services.OrderService:24219861
獲取到服務實例:DependencyInjectionDemo.Services.OrderServiceEx:38855053

這樣就可以獲取到兩個服務實例

刷新瀏覽器,再執行一遍

獲取到服務實例:DependencyInjectionDemo.Services.OrderService:24219861
獲取到服務實例:DependencyInjectionDemo.Services.OrderServiceEx:38855053
獲取到服務實例:DependencyInjectionDemo.Services.OrderService:24219861
獲取到服務實例:DependencyInjectionDemo.Services.OrderServiceEx:38855053

因為注冊的是單例,所以兩次請求獲取到的實例都是相同的

這樣做的好處是:一方面避免一個服務重復注冊,也可以控制一個服務需要注冊不同的實現

知識共享許可協議

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

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

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


免責聲明!

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



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