通常在使用 ASP.NET Core 依賴注入 (Dependency Injection, DI) 都是一個介面對應一個實作類別。
若有多個類別時做相同的介面時,注入的方式就會有點變化。
本篇將介紹 ASP.NET Core 依賴注入多個相同的介面 (Interface)
前置準備
以下介面作為範例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
   | public enum WalletType {     Alipay,     CreditCard,     LinePay }
  public interface IWalletService {     WalletType WalletType { get; }     void Debit(decimal amount); }
  public class AlipayService : IWalletService {     public WalletType WalletType { get; } = WalletType.Alipay;     public void Debit(decimal amount)     {              } }
  public class CreditCardService : IWalletService {     public WalletType WalletType { get; } = WalletType.CreditCard;     public void Debit(decimal amount)     {              } }
  public class LinePayService : IWalletService {     public WalletType WalletType { get; } = WalletType.LinePay;     public void Debit(decimal amount)     {              } }
   | 
服務註冊
用相同的介面,註冊不同的實作類別:
1 2 3 4 5 6 7 8 9 10 11 12
   | public class Startup {     public void ConfigureServices(IServiceCollection services)     {         services.AddMvc();
                   services.AddSingleton<IWalletService, AlipayService>();         services.AddSingleton<IWalletService, CreditCardService>();         services.AddSingleton<IWalletService, LinePayService>();     } }
   | 
Service Injection
在 Constructor Injection 時用 IEnumerable<T> 注入,便可取得相同介面的全部實例,再依照使用情境選擇要用的實例。範例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc;
  namespace MyWebsite.Controllers {     public class ShoppingCartController : Controller     {         private readonly IEnumerable<IWalletService> _walletServices;
          public ShoppingCartController(IEnumerable<IWalletService> walletServices)         {             _walletServices = walletServices;         }
          public IActionResult Checkout(WalletType walletType, decimal amount)         {             var walletService = _walletServices.Single(x => x.WalletType == walletType);             walletService.Debit(amount);             return Ok();         }     } }
   | 
示意圖如下:

注意!
通常只建議 Singleton 類型的服務這樣使用,因為使用 Transient 或 Scoped 類型的服務,注入時會 new 新的實例,若沒用到的話,就變成不必要的效能耗損。
如果服務註冊用相同的介面,註冊不同的實作類別,Constructor Injection 時不是用 IEnumerable<T> 注入,就只會得到最後一個註冊的類別,如上例會得到 LinePayService 的實例。
示意圖如下:
