WEB API 透過 Autofac 實作 Adapter pattern,以ATM查詢餘額為例
這陣子剛好接觸到公司的案子中,有使用Spring.NET在做DI,
有一部分的功能剛好很類似ATM在做餘額查詢的動作.
故想說採用Autofac來實作一個小型範例當作練習.
再此如果有描敘有誤的地方,也請各位前輩不吝指導!
情境
假設在生活中,我們需要透過ATM查詢餘額,
再行為動作上只要插入卡片,輸入密碼.
只要該ATM的銀行有跟目前的提供卡片銀行有連線關係就能查詢到該提款卡的餘額!
如下圖
我想在程式上這很好實現,最快的方法.我會想這樣寫
switch (bankProvider)
{
case "Bank-A":
Balance = 100;
break;
case "Bank-B":
Balance = 1200;
break;
case "Bank-C":
Balance = 1300;
break;
//已此類推....
}
但如果今天又再增加其他銀行,不就要一直在持續往下加了嗎?
如果要取消掉一家銀行不就又要再刪掉或註解掉一行程式碼了嗎?
如果今天有個中介可以幫我串接各家銀行,而他只需要知道這家卡片銀行是哪家,
自動分派至指定的銀行查詢餘額,然而當某家銀行沒介接時又能以不修改程式自動下架?

如上圖所示,透過QuerybalanceController,
帶入bankID經由MainAdapter,
找到對應繼承IProviderEntrance的Provider(Bank).
實作

將各個provider 如BankA,BankB....各自獨立為一個專案,
均繼承WEB_API.Provider.Interfaces中的IProviderEntrance.cs內的Interface
如下圖

實作GetBalance這個方法

上述功能有提到,假設某個銀行如果終止服務時,能夠不用透過修改程式也能正常運作!
所以在各個Provider的專案內,加入一個moduleConfig.cs 主要是除了讓我們能夠透過注入adaper中,
也能透過IsEnable此參數讓我們能透過autofac設定檔時能夠設定是否注入

接下來就是將所有繼承IProviderEntrance的Provider可以透過一個Adapters,
來找到個自的Provider,所以在WEB_API.Provider.Interfaces加入一個MainAdapter.cs
接著跟Provider一樣在WEB_API.Provider.Interfaces中,
新增一個moduleConfig.cs ,跟各個Provider中的差異就在於,
透過RegisterAdapter將每一個註冊IProviderEntrance放置在MainAdapter,
如下圖

web.config中加入設定,
載入指定模組BankA,BankA
並將Interface專案中的Adapter一同載入!
這邊說明一下IsEnable此參數就是為了達成假設今天某provider終止服務,而我們又不想更動程式碼,
此時將value設為false那麼將不會注入在容器中

Global.asax.cs 中啟用autofac ,
將web.config中的設定讀入,
並註冊進容器內

實作QuerybalanceController
由於在WEB_API.Provider.Interfaces中的moduleConfig.cs,
我們使用RegisterAdapter故將會把所有繼承IProviderEntrance實體對應到MainAdapter,
透過建構式注入,最後產生的會是 IEnumerable<MainAdapter> 的集合

測試
經過如此冗長...當然要測試一下呀))))
利用POSTMAN測試一下帶入BankA的參數

實際在QuerybalanceController下中斷點來瞧瞧!!
目前注入的實體確實有兩個,BankA,BankB,
然後透過Linq帶入BankId當作搜尋條件,假設沒有的時候就輸出預設值


那麼假設BankA已經終止服務呢?需要修改程式嗎?
到web.config中將剛剛BankA的設定IsEnable的value設定為false

我們再帶入相同參數試試


BankA的實體消失了,並未注入進來!
所以看來也完成上述的功能,不必更動任何程式碼就能將不需要的服務給卸下,
往後如果有BankC,BankD....透過interfacer實作加入設定檔也可以很輕鬆的切換,
不用更動前面的邏輯省了不少麻煩~~
最後附上範例程式碼Github連結:請點我