LayIM.AspNetCore Middleware 開發日記(二)預備知識介紹

丶Pz發表於2018-05-29

前言

  開發一個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中有一個型別為RequestDelegatenext變數。這樣就使得呼叫鏈串聯起來。我們通過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"),
            });

  可以看到,FileProviderEmbeddedFileProvider,其中傳入了兩個引數,一個是程式集,一個是靜態資源的名稱空間。

  不過當我們新增靜態檔案之後需要注意的是,要將檔案生成操作屬性設定成為嵌入的資源,否則訪問不到。(不過還有使用配置檔案的做法)

  那麼這樣的話,我們訪問一下靜態資源,效果如下:

  

 

  那麼動態資源和靜態資源都可以訪問了,那麼我們就可以進行下一步的工作了。

總結

   本文簡單介紹了中介軟體的基礎知識和使用方式、嵌入資源的訪問以及依賴注入的簡單使用,之所以說是預備知識,是因為在後續的開發過程中都會使用到。

   部落格預告:LayIM.AspNetCore Middleware 開發日記(三)基礎框架搭建

   專案地址:https://github.com/fanpan26/LayIM.AspNetCore (本文程式碼對應blog2分支)歡迎小夥伴們star 圍觀 提意見。

相關文章