ASP.NET Core如何注入多個(gè)服務(wù)實(shí)現(xiàn)類
前言:
依賴注入在 ASP.NET Core 中起中很重要的作用,也是一種高大上的編程思想,它的總體原則就是:俺要啥,你就給俺送啥過來。服務(wù)類型的實(shí)例轉(zhuǎn)由容器自動(dòng)管理,無需我們在代碼中顯式處理。
因此,有了依賴注入后,你的編程思維就得變一變了。在過去,許多功能性的類型(比如一個(gè)加密解密的類),我們都喜歡將其定義為靜態(tài)(static),而有了依賴注入,你就要避免使用靜態(tài)類型,應(yīng)該交由服務(wù)容器幫你管理,只要你用好了,你會(huì)發(fā)現(xiàn)依賴注入是很方便的。
依賴注入的初級(jí)玩法,也是比較標(biāo)準(zhǔn)的玩法,此種玩法有兩種模式:
- 十代單傳模式:一個(gè)接口對應(yīng)一個(gè)類,比如先定義接口 IA、IB,隨后,類A實(shí)現(xiàn) IA,類B 實(shí)現(xiàn) IB。一對一。也可以是抽象類(或基類)E,然后 F 繼承 E 類。
- 斷子絕孫模式:直接就寫一個(gè)類,不考慮派生,直接就添加到服務(wù)容器中。
來,看個(gè)例子。
1、定義個(gè)接口
public interface IPlayGame { void Play(); }
然后,寫一個(gè)類來實(shí)現(xiàn)它。
public class NBPlayGame : IPlayGame { public void Play() { Console.WriteLine("全民打麻藥。"); } }
我們知道,所謂服務(wù)類,其實(shí)就是普通類,這些類一般用于完成某些功能,比如計(jì)算 MD5 值。接著呢,還記得 Startup 類有個(gè) ConfigureServices 方法吧,對,就在這廝里面把我們剛剛那個(gè)服務(wù)進(jìn)行注冊(就是添加到 ServiceCollection 集合中)。
public void ConfigureServices(IServiceCollection services) { services.AddTransient<IPlayGame, NBPlayGame>(); }
添加的時(shí)候很簡單,類型一對一,IPlayGame 接口與 NBPlayGame 類對應(yīng)。添加時(shí)有三種方法你可以調(diào)用,實(shí)際上對應(yīng)著,服務(wù)類在容器中的生命周期。
AddSingleton:
單個(gè)實(shí)例,這是壽命最長的,與天同壽。整個(gè)應(yīng)用程序中僅用一個(gè)實(shí)例。AddTransient
:這個(gè)是最短命的,可能是天天晚上加班熬夜,死得很快。此種情況下,服務(wù)類的實(shí)例是用的時(shí)候創(chuàng)建,用完后直接銷毀。AddScoped
:這個(gè)比較難理解。它的生命周期在單個(gè)請求內(nèi),包括客戶端與服務(wù)器之間隨后產(chǎn)生的子請求,反正只要請求的會(huì)話結(jié)束了,就會(huì)清理。
2、注入服務(wù)
比如在中間件,在控制器,或者在其他服務(wù)類的構(gòu)造函數(shù)上(中間件是在 Invoke / InvokeAsync 方法上)進(jìn)行實(shí)例接收。
現(xiàn)在來用一下,寫一個(gè)中間件。
public class TestMiddleware { public TestMiddleware(RequestDelegate next) { } public Task InvokeAsync(HttpContext context, IPlayGame game) { game.Play(); return Task.CompletedTask; } }
已注冊的服務(wù)會(huì)注入到 InvokeAsync 方法的參數(shù)中。注意第一個(gè)參數(shù)是 HttpContext,這是必須參數(shù),后面的是注入的參數(shù)。
最后,在 Startup 類的 Configure 方法中就可以 use 這個(gè)中間件了。
public void Configure(IApplicationBuilder app) { app.UseMiddleware<TestMiddleware>(); }
運(yùn)行后,Play 方法調(diào)用,在控制臺(tái)中輸出以下結(jié)果
3、功能類
也稱“斷子絕孫”模式,不使用接口規(guī)范,直接寫功能類。
public class DoSomething { public string GetMessage() => "你好,剛才 Boss 找你。"; }
注冊服務(wù)時(shí)更簡單。
public void ConfigureServices(IServiceCollection services) { services.AddScoped<DoSomething>(); }
在 Configure 方法中進(jìn)行注入。
public void Configure(IApplicationBuilder app, DoSomething thing) { Console.WriteLine(thing.GetMessage()); }
運(yùn)行后,輸出結(jié)果如下
在容器中,使用 ServiceDescriptor 類來存儲(chǔ)服務(wù)類型相關(guān)的信息。其中,ServiceType 表示的是服務(wù)的類型,如果服務(wù)是有接口與實(shí)現(xiàn)類的,那么這個(gè)屬性指的是接口的類型,實(shí)現(xiàn)類的類型信息由 ImplementationType 屬性存儲(chǔ)。如果沒有接口,直接只定義類型,那么這個(gè)類型的信息就存到 ServiceType 屬性上,ImplementationType 屬性不使用。
上面這些例子中,ServiceType 是 IPlayGame 接口相關(guān)信息,ImplementationType 是 NBPlayGame 類的信息。如果像上面 DoSomething 類的情況,則 ServiceType 為 DoSomething 相關(guān)的信息,ImplementationType 為空。
4、高級(jí)類
接下來,咱們看高級(jí)玩法。
定義一個(gè)接口。
public interface IDemoService { string Version { get; } void Run(); }
然后,有兩個(gè)類實(shí)現(xiàn)這個(gè)接口。
public class DemoService1 : IDemoService { public string Version => "v1"; public void Run() { Console.WriteLine("第一個(gè)服務(wù)實(shí)現(xiàn)類。"); } } public class DemoService2 : IDemoService { public string Version => "v2"; public void Run() { Console.WriteLine("第二個(gè)服務(wù)實(shí)現(xiàn)類。"); } }
然后,我們注冊服務(wù)。
public void ConfigureServices(IServiceCollection services) { services.AddTransient<IDemoService, DemoService1>(); services.AddTransient<IDemoService, DemoService2>(); }
然后我們照例,接收注入,咱們依舊使用中間件的方法參數(shù)接收。
public class DemoMiddleware { public DemoMiddleware(RequestDelegate next) { // 由于程序約定,此構(gòu)造函數(shù)必須提供。 } public async Task InvokeAsync(HttpContext context, IDemoService sv) { await context.Response.WriteAsync(sv.Version); } }
然后,在 Startup.Configure 方法中使用該中間件。
public void Configure(IApplicationBuilder app, DoSomething thing) { app.UseMiddleware<DemoMiddleware>(); }
運(yùn)行之后,你發(fā)現(xiàn)問題了,看看輸出。
出事了,參數(shù)僅能接收到最后注冊的實(shí)現(xiàn)類型實(shí)例,也就是 DemoService2 類。所以就看到網(wǎng)上有不少朋友發(fā)貼問了,.NET Core 是不是不支持多個(gè)服務(wù)實(shí)現(xiàn)類的注入?這難倒了很多人。
實(shí)話告訴你,Core Core 兄是支持注入多個(gè)實(shí)現(xiàn)類的實(shí)例的。
下面,老周介紹兩種解決方法(其實(shí)有三種,還有一種不太好弄,尤其是你對 Core 兄不熟的時(shí)候,所以我說兩種,基本夠用)。
方法一、接收 IServiceProvider 類型的注入。
public async Task InvokeAsync(HttpContext context, IServiceProvider provider) { StringBuilder sb = new StringBuilder(); foreach (var sv in provider.GetServices<IDemoService>()) { sb.Append($"{sv.Version}<br/>"); } await context.Response.WriteAsync(sb.ToString()); }
只要能接收到 IServiceProvider 所引用的實(shí)例,就能通過 GetServices 方法獲取多個(gè)服務(wù)實(shí)例。
方法二,這種方法老周很推薦,更簡單,直接注入 IEnumerable<T> 類型,本例中就是 IEnumerable<IDemoService>。
public async Task InvokeAsync(HttpContext context, IEnumerable<IDemoService> svs) { StringBuilder sb = new StringBuilder(); foreach (var sv in svs) { sb.Append($"{sv.Version}<br/>"); } await context.Response.WriteAsync(sb.ToString()); }
IEnumerable<T> 的妙處就是可以 foreach ,這樣你也能訪問多個(gè)實(shí)例,而且必要時(shí)還可以聯(lián)合 LINQ 一起耍。
運(yùn)行結(jié)果如下。
到此這篇關(guān)于ASP.NET Core如何注入多個(gè)服務(wù)實(shí)現(xiàn)類的文章就介紹到這了,更多相關(guān)ASP.NET Core何注多個(gè)服務(wù)實(shí)現(xiàn)類內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 理解ASP.NET Core 依賴注入(Dependency Injection)
- asp.net core3.1cookie和jwt混合認(rèn)證授權(quán)實(shí)現(xiàn)多種身份驗(yàn)證方案
- 理解ASP.NET Core 啟動(dòng)類(Startup)
- 理解ASP.NET Core 中間件(Middleware)
- 關(guān)于Jenkins + Docker + ASP.NET Core自動(dòng)化部署的問題(避免踩坑)
- asp.net core MVC之實(shí)現(xiàn)基于token的認(rèn)證
- ASP.NET Core 集成 React SPA應(yīng)用的步驟
- ASP.NET Core 文件響應(yīng)壓縮的常見使用誤區(qū)
- ASP.NET Core中間件初始化的實(shí)現(xiàn)
- ASP.NET Core讀取Request.Body的正確方法
- ASP.NET Core Web API 教程Project Configuration
相關(guān)文章
深入分析XmlSerializer對象的Xml序列化與反序列化的示例詳解
本篇文章是對XmlSerializer 對象的Xml序列化與反序列化的應(yīng)用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05asp.net core使用DevExtreme20將int列轉(zhuǎn)為checkbox方法示例
這篇文章主要為大家介紹了asp.net core使用DevExtreme20將int列轉(zhuǎn)為checkbox方法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08.Net實(shí)現(xiàn)圖片裁剪圖片縮放及圖片加水印詳解
這篇文章主要為大家介紹了.Net實(shí)現(xiàn)圖片裁剪圖片縮放及圖片加水印實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09使用.NET6實(shí)現(xiàn)動(dòng)態(tài)API
本文詳細(xì)講解了使用.NET6實(shí)現(xiàn)動(dòng)態(tài)API,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12ASP.NET Core WebSocket集群實(shí)現(xiàn)思路詳解
這篇文章主要為大家介紹了ASP.NET Core WebSocket集群實(shí)現(xiàn)思路詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11.Net性能調(diào)優(yōu)-ArrayPool詳情
ArrayPool具有高性能 托管 數(shù)組緩沖池,可重復(fù)使用,用 租用 空間的方式代替 重新分配 數(shù)組空間的行為的特點(diǎn)及可以在頻繁創(chuàng)建和銷毀數(shù)組的情況下 提高性能 ,減少垃圾回收器的壓力的優(yōu)點(diǎn),下面文章內(nèi)容將詳細(xì)對其做介紹,需要的朋友可以參考一下2021-09-09