前言
開發一個AspNetCore的中介軟體需要理解RequestDelegate。另外,還需要理解.NET Core中的依賴注入。還有一個就是內嵌資源的訪問。例如:EmbeddedFileProvider 的使用。那麼本文就這三點做一個簡單的介紹。理解了這些那麼基本上開發下去就不難了。
RequestDelegate
對於RequestDelegate的介紹,大家可以看一下這篇文章:https://www.cnblogs.com/artech/p/inside-asp-net-core-pipeline-01.html。
我這裡就簡單通過程式碼過一下,下面是一個簡單的HelloWorld的例子。
namespace LayIM.AspNetCore.WebDemo.Middleware { public class HelloWorldMiddleWare { private readonly RequestDelegate next; public HelloWorldMiddleWare(RequestDelegate next) { this.next = next; } public async Task Invoke(HttpContext context) { await context.Response.WriteAsync("hello world"); } } public static class HelloWorldExtensions { public static void UseHelloWorld(IApplicationBuilder builder) { builder.UseMiddleware<HelloWorldMiddleWare>(); } } }
然後在Startup中將這個中介軟體註冊到IApplicationBuilder中即可。就像 app.UseMvc() 一樣。
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseHelloWorld(); }
看一下執行效果:
那麼這個就是RequestDelegate的用法,那麼我們可以看到,在HelloWorldMiddleware中有一個型別為RequestDelegate的next變數。這樣就使得呼叫鏈串聯起來。我們通過RequestDelegate 就能做一些全域性性的工作了,比如請求校驗,篩選,日誌,統計等等,看需求吧。然後在根據情況選擇是否執行 next?.Invoke(context) 方法,將請求流程走下去,直到走完所有流程或者走到某個被攔截掉的流程為止。同樣的道理,在LayIM.AspNetCore 中攔截了開頭為{/layim}的請求。否則繼續 執行其他業務邏輯。示例程式碼如下:
if (context.IsLayIMRequest(options) == false) { await next?.Invoke(context); return; }
雖然沒有加註釋,但是也能看得出來,判斷是否是LayIM的請求,如果不是,直接跳過。
DependencyInjection
依賴注入相信大家都很熟悉了,要說他有什麼好處,最直觀的一個好處就是解耦。在之前的LayIM_NetClient專案中,我是直接將融雲的實現放到中介軟體中,這種就是耦合性太高。使用者如果不想使用融雲的話,就沒法用了。那麼在LayIM.AspNetCore 專案中,通過使用依賴注入的方式,將核心介面與實現類分離,達到不用改核心程式碼,直接擴充套件新的實現類即可做到業務實現轉換。這裡我直接用專案中的例子作為介紹:
在初始化Middleware的時候,系統會自動將IServiceProvider注入到中介軟體中
public LayIMMiddleware(RequestDelegate next, LayIMOptions options,IServiceProvider serviceProvider) { this.next = next; this.options = options; this.serviceProvider = serviceProvider; LayIMServiceLocator.SetServiceProvider(this.serviceProvider); }
我通過LayIMServiceLocator 來儲存IServiceProvider的例項,那麼在使用的時候。通過它就可以得到我們想要的服務了。下面是一個獲取Token的例子。在ILayIMServer 介面中定義瞭如下方法:
TokenResult GetToken(string userId);
然後在新的RongCloud專案中實現該方法,並且擴充套件IServiceCollection
public class RongCloudServer : ILayIMServer { private readonly RongCloudConfig config; public RongCloudServer(RongCloudConfig config) { this.config = config; } public TokenResult GetToken(string userId) { return new TokenResult { code = 0, msg = "ok", token = "123456" }; } }
public static void AddLayIM(this IServiceCollection services, RongCloudConfig config) { services.AddSingleton(config); services.AddSingleton<ILayIMServer, RongCloudServer>(); }
那麼,在Demo中我們可以這麼使用了:
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddLayIM(config => { config.AppKey = "123456"; config.AppSecret = "654321"; }); }
這裡呢,如果不想使用融雲通訊的話,可以自己去實現ILayIMServer介面,然後做自己的擴充套件即可。
核心端依賴於介面,處理邏輯如下:(其他程式碼可先忽略,暫時看中間兩行程式碼)
//獲取連線websocket的token routes.AddQueryCommand("/token", context => { var server = LayIMServiceLocator.GetService<ILayIMServer>(); return server.GetToken(context.Request.Query["uid"]); });
可以看到,先通過ServiceLocator獲取了ILayIMServer介面,然後呼叫介面方法即可。這樣就達到了框架程式碼與實現程式碼解耦的目的。我們看一下效果:
程式碼執行正常,在這裡呢不在演示其他實現。如果不明白的小夥伴可以去下載程式碼除錯,或者直接私信我即可。
EmbeddedFileProvider
好文推薦:https://www.cnblogs.com/artech/p/net-core-file-provider-04.html
大家知道,正如SwaggerUI那樣,為什麼我們配置了,就能訪問到UI介面呢?他的資原始檔在哪裡呢?其實這就是內嵌資源起到的作用。想深入理解的小夥伴可以查閱其他資料,這裡我只是簡單介紹如何去實現內嵌資源的訪問。
其實很簡單,如下幾句程式碼就搞定:
app.UseFileServer(new FileServerOptions { RequestPath = options.ApiPrefix, FileProvider = new EmbeddedFileProvider(assembly, "namespace"), });
可以看到,FileProvider是EmbeddedFileProvider,其中傳入了兩個引數,一個是程式集,一個是靜態資源的名稱空間。
不過當我們新增靜態檔案之後需要注意的是,要將檔案生成操作屬性設定成為嵌入的資源,否則訪問不到。(不過還有使用配置檔案的做法)
那麼這樣的話,我們訪問一下靜態資源,效果如下:
那麼動態資源和靜態資源都可以訪問了,那麼我們就可以進行下一步的工作了。
總結
本文簡單介紹了中介軟體的基礎知識和使用方式、嵌入資源的訪問以及依賴注入的簡單使用,之所以說是預備知識,是因為在後續的開發過程中都會使用到。
部落格預告:LayIM.AspNetCore Middleware 開發日記(三)基礎框架搭建
專案地址:https://github.com/fanpan26/LayIM.AspNetCore (本文程式碼對應blog2分支)歡迎小夥伴們star 圍觀 提意見。