.NET Core中的一个接口多种实现的依赖注入与动态选择
最近有個(gè)需求就是一個(gè)抽象倉(cāng)儲(chǔ)層接口方法需要SqlServer以及Oracle兩種實(shí)現(xiàn)方式,為了靈活我在依賴注入的時(shí)候把這兩種實(shí)現(xiàn)都給注入進(jìn)了依賴注入容器中,但是在服務(wù)調(diào)用的時(shí)候總是獲取到最后注入的那個(gè)方法的實(shí)現(xiàn),這時(shí)候就在想能不能實(shí)現(xiàn)動(dòng)態(tài)的選擇使用哪種實(shí)現(xiàn)呢?如果可以的話那么我只需要在配置文件中進(jìn)行相應(yīng)的配置即可獲取到正確的實(shí)現(xiàn)方法的調(diào)用,這樣的話豈不快哉!今天我們就來一起探討下實(shí)現(xiàn)這種需求的幾種實(shí)現(xiàn)方式吧。
作者:依樂祝
原文地址:https://www.cnblogs.com/yilezhu/p/10236163.html
代碼演示
在開始實(shí)現(xiàn)的方式之前,我們先模擬下代碼。由于真實(shí)系統(tǒng)的結(jié)構(gòu)比較復(fù)雜,所以這里我就單獨(dú)建一個(gè)類似的項(xiàng)目結(jié)構(gòu)代碼。項(xiàng)目如下圖所示:
接下來我來詳細(xì)說下上面的結(jié)果作用及代碼。
MultiImpDemo.I 這個(gè)項(xiàng)目是接口項(xiàng)目,里面有一個(gè)簡(jiǎn)單的接口定義ISayHello,代碼如下:
? ?public interface ISayHello{ ? ? ? ?string Talk();}很簡(jiǎn)單,就一個(gè)模擬講話的方法。
MultiImpDemo.A 這個(gè)類庫(kù)項(xiàng)目是接口的一種實(shí)現(xiàn)方式,里面有一個(gè)SayHello類用來實(shí)現(xiàn)ISayHello接口,代碼如下:
MultiImpDemo.B 這個(gè)類庫(kù)項(xiàng)目是接口的另一種實(shí)現(xiàn)方式,里面也有一個(gè)SayHello類用來實(shí)現(xiàn)ISayHello接口,代碼如下:
MultiImpDemo.Show 這個(gè)就是用來顯示我們模擬效果的API項(xiàng)目,首選我們?cè)贑onfigureServices中加入如下的代碼來進(jìn)行上述兩種實(shí)現(xiàn)方式的注入:
在api實(shí)現(xiàn)里面獲取服務(wù)并進(jìn)行模擬調(diào)用:
代碼很簡(jiǎn)單對(duì)不對(duì)?你應(yīng)該看的懂吧,這時(shí)候我們運(yùn)行起來項(xiàng)目,然后訪問API'api/values'這個(gè)接口,結(jié)果總是顯示如下的結(jié)果:
兩種需求對(duì)應(yīng)兩種實(shí)現(xiàn)
這里有兩種業(yè)務(wù)需求!第一種業(yè)務(wù)中只需要對(duì)其中一種實(shí)現(xiàn)方式進(jìn)行調(diào)用,如:業(yè)務(wù)需要SqlServer數(shù)據(jù)庫(kù)的實(shí)現(xiàn)就行了。第二種是業(yè)務(wù)中對(duì)這兩種實(shí)現(xiàn)方式都有用到,如:業(yè)務(wù)急需要用到Oracle的數(shù)據(jù)庫(kù)實(shí)現(xiàn)同時(shí)也有用到SqlServer的數(shù)據(jù)庫(kù)實(shí)現(xiàn),需要同時(shí)往這兩個(gè)數(shù)據(jù)庫(kù)中插入相同的數(shù)據(jù)。下面分別對(duì)這兩種需求進(jìn)行解決。
業(yè)務(wù)中對(duì)這兩種實(shí)現(xiàn)方式都有用到
針對(duì)這種情況有如下兩種實(shí)現(xiàn)方式:
第二種實(shí)現(xiàn)方式
其實(shí),在ASP.NET Core中,當(dāng)你對(duì)一個(gè)接口注冊(cè)了多個(gè)實(shí)現(xiàn)的時(shí)候,構(gòu)造函數(shù)是可以注入一個(gè)該接口集合的,這個(gè)集合里是所有注冊(cè)過的實(shí)現(xiàn)。
下面我們先改造下ConfigureServices,分別注入下這兩種實(shí)現(xiàn)
接著繼續(xù)改造下注入的方式,這里我們直接注入IEnumerable<ISayHello>如下代碼所示:
然后運(yùn)行起來看下效果吧
利用AddTransient的擴(kuò)展方法public static IServiceCollection AddTransient<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class;然后根據(jù)我們的配置的實(shí)現(xiàn)來進(jìn)行服務(wù)實(shí)現(xiàn)的獲取。下面就讓我們利用代碼來實(shí)現(xiàn)一番吧:
然后我們具體調(diào)用的依賴注入的方式需要變化一下:
然后運(yùn)行看下效果吧:
可以看到A跟B的實(shí)現(xiàn)都獲取到了!效果實(shí)現(xiàn)!
業(yè)務(wù)只需要對(duì)其中一種實(shí)現(xiàn)方式的調(diào)用
這時(shí)候我們可以根據(jù)我們預(yù)設(shè)的配置來動(dòng)態(tài)獲取我們所需要的實(shí)現(xiàn)。這段話說的我自己都感覺拗口。話不多少,開魯吧!這里我將介紹三種實(shí)現(xiàn)方式。
根據(jù)我們的配置文件中設(shè)置的key來進(jìn)行動(dòng)態(tài)的注入。
這種方式實(shí)現(xiàn)之前首先得進(jìn)行相應(yīng)的配置,如下所示:
?"CommonSettings": { ? ?"ImplementAssembly": "MultiImpDemo.A"}然后在注入的時(shí)候根據(jù)配置進(jìn)行動(dòng)態(tài)的進(jìn)行注入:
services.AddTransient<ISayHello, A.SayHello>(); ? ? ? ? ? ?services.AddTransient<ISayHello, B.SayHello>();然后在服務(wù)調(diào)用的時(shí)候稍作修改:
OK,到這里運(yùn)行一下看下效果吧!然后改下配置文件再看下效果!
第二種實(shí)現(xiàn)方式,即接口參數(shù)的方式這樣可以避免上個(gè)方法中反射所帶來的性能損耗。
這里我們改造下接口,接口中加入一個(gè)程序集的屬性,如下所示:
public interface ISayHello{ ? ? ? ?string ImplementAssemblyName { get; } ? ? ? ?string Talk();}對(duì)應(yīng)的A跟B中的實(shí)現(xiàn)代碼也要少做調(diào)整:
A:
public string ImplementAssemblyName => "MultiImpDemo.A"; ? ? ? ?public string Talk(){ ? ? ? ? ? ?return "Talk from A.SayHello";}
B:
public string ImplementAssemblyName => "MultiImpDemo.B"; ? ? ??public string Talk(){ ? ? ? ? ? ?return "Talk from B.SayHello";}
然后,在實(shí)現(xiàn)方法調(diào)用的時(shí)候稍微修改下:
效果自己運(yùn)行下看下吧!
第三種實(shí)現(xiàn)是根據(jù)配置進(jìn)行動(dòng)態(tài)的注冊(cè)
首先修改下ConfigureServices方法:
這樣的話就會(huì)根據(jù)我們的配置文件來進(jìn)行動(dòng)態(tài)的注冊(cè),然后我們像往常一樣進(jìn)行服務(wù)的調(diào)取即可:
?private readonly ISayHello _sayHello; ? ? ? ?public ValuesController(ISayHello sayHello) ? ? ? ?{_sayHello = sayHello;} ? ? ? ?// GET api/values[] ? ? ? ?public ActionResult<IEnumerable<string>> Get(){ ? ? ? ? ? ?return new string[] { _sayHello.Talk() };}運(yùn)行即可得到我們想要的效果!
總結(jié)
本文從具體的業(yè)務(wù)需求入手,根據(jù)需求來或動(dòng)態(tài)的進(jìn)行對(duì)應(yīng)服務(wù)的獲取,或同時(shí)使用兩個(gè)不同的實(shí)現(xiàn)!希望對(duì)您有所幫助!如果您有更多的實(shí)現(xiàn)方法可以在下方留言,或者加入.NET Core實(shí)戰(zhàn)千人群跟637326624大伙進(jìn)行交流,最后感謝您的閱讀!
總結(jié)
以上是生活随笔為你收集整理的.NET Core中的一个接口多种实现的依赖注入与动态选择的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何测试 ASP.NET Core We
- 下一篇: .Net Core分布式部署中的Data