在日常使用ASP.NET Core开发的过程中我们多多少少会设计到使用中间件的场景,ASP.NET Core默认也为我们内置了许多的中间件,甚至有时候我们需要自定义中间件来帮我们处理一些请求管道过程中的处理。接下来,我们将围绕着以下几个问题来简单探究一下,关于ASP.NET Core中间件是如何初始化的
首先,使用UseMiddleware注册自定义中间件和直接Use的方式有何不同
其次,使用基于约定的方式定义中间件和使用实现IMiddleware接口的方式定义中间件有何不同
再次,使用基于约定的方式自定义中间件的究竟是如何约束我们编写的类和方法格式的
最后,使用约定的方式定义中间件,通过构造注入和通过Invoke方法注入的方式有何不同
接下来我们将围绕这几个核心点来逐步探究关于ASP.NET Core关于中间件初始化的神秘面纱,来指导我们以后使用它的时候需要有注意点,来减少踩坑的次数。
自定义的方式使用自定义中间件的方式有好几种,咱们简单来演示一下三种比较常用方式。
Use方式首先,也是最直接最简单的使用Use的方式,比如
app.Use(async (context, next) => { var endpoint = context.Features.Get<IEndpointFeature>()?.Endpoint; if (endpoint != null) { ResponseCacheAttribute responseCache = endpoint.Metadata.GetMetadata<ResponseCacheAttribute>(); if (responseCache != null) { //做一些事情 } } await next(); }); 基于约定的方式然后使用UseMiddleware也是我们比较常用的一种方式,这种方式使用起来相对于第一种来说,虽然使用起来可能会稍微繁琐一点,毕竟需要定义一个类,但是更好的符合符合面向对象的封装思想,它的使用方式大致如下,首先定义一个Middleware的类
public class RequestCultureMiddleware { private readonly RequestDelegate _next; public RequestCultureMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var cultureQuery = context.Request.Query["culture"]; if (!string.IsNullOrWhiteSpace(cultureQuery)) { var culture = new CultureInfo(cultureQuery); CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = culture; } await _next(context); } }编写完成之后,需要手动的将类注册到管道中才能生效,注册方式如下所示
app.UseMiddleware<RequestCultureMiddleware>(); 实现IMiddleware的方式还有一种方式是实现IMiddleware接口的方式,这种方式比如前两种方式常用,但是也确确实实的存在于ASP.NET Core中,既然存在也就有它存在的理由,我们也可以探究一下,它的使用方式也是需要自定义一个类去实现IMiddleware接口,如下所示
public class RequestCultureOtherMiddleware:IMiddleware { public async Task InvokeAsync(HttpContext context, RequestDelegate next) { var cultureQuery = context.Request.Query["culture"]; if (!string.IsNullOrWhiteSpace(cultureQuery)) { var culture = new CultureInfo(cultureQuery); CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = culture; } await next(context); } }这种方式和第二种方式略有不同,需要手动将中间件注册到容器中,至于声明周期也没做特殊要求,可以直接注册为单例模式
services.AddSingleton<IMiddleware,RequestCultureOtherMiddleware>();完成上步操作之后,同样也需要将其注册到管道中去
app.UseMiddleware<RequestCultureOtherMiddleware>();这种方式相对于第二种方式的主要区别在于灵活性方面的差异,它实现了IMiddleware接口,那就要受到IMiddleware接口的约束,也就是我们常说的里氏代换原则,首先我们可以先来看下IMiddleware接口的定义[core/blob/v5.0.4/src/Http/Http.Abstractions/src/IMiddleware.cs" target="_blank">点击查看源码