• ASP.NET Core - 自定义中间件


    上一章讲了请求管道与中间件的基本概念和工作模式,也介绍了 ASP.NET Core 中内置的中间件,这一章介绍一下如何自定义中间件,这是很常用也很重要的内容,日常工作中很多场景我们都可以自定义自己的中间件,通过对请求管道进行拦截执行我们自己的业务逻辑,实现各种需求。这也是 ASP.NET Core 框架下的一种最基本的 AOP 编程方式。

    中间件本质上是一个委托,上一章的例子中我们将中间件的代码逻辑通过Use()、Run()、Map() 等方法写在了入口文件中,这样很不优雅。我们可以对这些代码进行封装,最简单的封装方式,就是通过一个静态类将相关的代码写成静态方法,在 Use() 等方法中只需要传入静态方法即可。但是这种方法一样不够优雅,我们可以模仿微软内置中间件和一些第三方组件提供的中间件的封装方式。例如,静态文件中间件的实现源码:

    image

    其实对于中间件的封装,可以不实现某个接口,但是它有一套约定的规则。
    (1) 中间件类名必须是 XXXMiddleware 格式
    (2) 中间件类中必须有 public Task Invoke(HttpContext context) 方法

    所以对于上面例子中的代码,我们可以进行以下的优化

    namespace MiddlewareSample.Middlewares
    {
        public class HelloMiddleware
        {
            private readonly RequestDelegate _next;
            // 注入相应的依赖,这里是下一个中间件的委托,如果有其他依赖项需要用到,也可以从构造函数注入
            public HelloMiddleware(RequestDelegate next)
            {
                _next = next;
            }
    
            public async Task Invoke(HttpContext context)
            {
                await context.Response.WriteAsync("Hello Middlerware1 ! ");
                if (context.Request.Query.TryGetValue("query", out var query))
                {
                    await context.Response.WriteAsync(query);
                }
                // 调用下一个中间件
                await _next(context);
                await context.Response.WriteAsync("End Middleware1 ! ");
            }
        }
    }
    

    之后再提供一个扩展方法,以供使用者便捷地进行注册使用。

    using MiddlewareSample.Middlewares;
    
    namespace Microsoft.AspNetCore.Builder
    {
        public static class HelloExtensions
        {
            public static IApplicationBuilder UseHello(this IApplicationBuilder app) 
            { 
                if(app == null)
                {
                    throw new ArgumentNullException(nameof(app));
                }
                // 中间件的注册方式
                app.UseMiddleware();
                return app;
            }
        }
    }
    

    这里使用了另一种中间件的注入方式,通过查看源码,可以看到最终也是调用了 Use() 方法进行注册的。在这个过程中,会通过反射等手段通过我们封装好的中间件类生成一个委托。

    image

    之后就是配置使用了,在 入口文件中将原本的 Use() 方法替换成扩展方法。

    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    
    app.UseDefaultFiles();
    app.UseStaticFiles();
    
    app.UseHello();
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Hello last Middleware ! ");
    });
    
    app.Run();
    

    最终的执行结果是一样的。

    image



    ASP.NET Core 系列:
    目录:ASP.NET Core 系列总结
    上一篇:ASP.NET Core - 请求管道与中间件

  • 相关阅读:
    C++Qt开发——SMTP协议
    浅析kubernetes中client-go Informer
    【KOS】安装卸载软件
    [RK3568][Android11] Android音量控制流程
    MySQL调优之慢查询日志应用
    Android Parcelable反序列化漏洞分析与利用
    docker&kubernets篇(二十)
    Analyzing User-Level Privacy Attack Against Federated Learning
    ArcGIS将两个相同范围但不同比例或位置的矢量数据移动到相同位置
    Linux下的一些工具
  • 原文地址:https://www.cnblogs.com/wewant/p/17107516.html