通常在使用 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
的實例。
示意圖如下: