IMiddlewareFactory/IMiddleware 是中间件激活的扩展点。
UseMiddleware 扩展方法检查中间件的已注册类型是否实现 IMiddleware。 如果是,则使用在容器中注册的 IMiddlewareFactory 实例来解析 IMiddleware 实现,而不使用基于约定的中间件激活逻辑。 中间件在应用的服务容器中注册为作用域或瞬态服务。
优点:
按客户端请求(作用域服务的注入)激活
让中间件强类型化
IMiddleware 按客户端请求(连接)激活,因此作用域服务可以注入到中间件的构造函数中。
IMiddleware
IMiddleware 定义应用的请求管道的中间件。InvokeAsync(HttpContext, RequestDelegate) 方法处理请求,并返回代表中间件执行的 Task。
使用约定激活的中间件:
public class ConventionalMiddleware
{private readonly RequestDelegate _next;public ConventionalMiddleware(RequestDelegate next){_next = next;}public async Task InvokeAsync(HttpContext context, AppDbContext db){var keyValue = context.Request.Query["key"];if (!string.IsNullOrWhiteSpace(keyValue)){db.Add(new Request(){DT = DateTime.UtcNow, MiddlewareActivation = "ConventionalMiddleware", Value = keyValue});await db.SaveChangesAsync();}await _next(context);}
}
使用 MiddlewareFactory 激活的中间件:
public class FactoryActivatedMiddleware : IMiddleware
{private readonly AppDbContext _db;public FactoryActivatedMiddleware(AppDbContext db){_db = db;}public async Task InvokeAsync(HttpContext context, RequestDelegate next){var keyValue = context.Request.Query["key"];if (!string.IsNullOrWhiteSpace(keyValue)){_db.Add(new Request(){DT = DateTime.UtcNow, MiddlewareActivation = "FactoryActivatedMiddleware", Value = keyValue});await _db.SaveChangesAsync();}await next(context);}
}
程序会为中间件创建扩展:
public static class MiddlewareExtensions
{public static IApplicationBuilder UseConventionalMiddleware(this IApplicationBuilder builder){return builder.UseMiddleware<ConventionalMiddleware>();}public static IApplicationBuilder UseFactoryActivatedMiddleware(this IApplicationBuilder builder){return builder.UseMiddleware<FactoryActivatedMiddleware>();}
}
无法通过 UseMiddleware 将对象传递给工厂激活的中间件:
public static IApplicationBuilder UseFactoryActivatedMiddleware(this IApplicationBuilder builder, bool option)
{// Passing 'option' as an argument throws a NotSupportedException at runtime.return builder.UseMiddleware<FactoryActivatedMiddleware>(option);
}
将工厂激活的中间件添加到 Startup.ConfigureServices
的内置容器中:
public void ConfigureServices(IServiceCollection services)
{services.AddDbContext<AppDbContext>(options =>options.UseInMemoryDatabase("InMemoryDb"));services.AddTransient<FactoryActivatedMiddleware>();services.AddRazorPages();
}
两个中间件均在 Startup.Configure
的请求处理管道中注册:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler("/Error");}app.UseConventionalMiddleware();app.UseFactoryActivatedMiddleware();app.UseStaticFiles();app.UseRouting();app.UseEndpoints(endpoints =>{endpoints.MapRazorPages();});
}
IMiddlewareFactory
IMiddlewareFactory 提供中间件的创建方法。 中间件工厂实现在容器中注册为作用域服务。
可在 Microsoft.AspNetCore.Http 包中找到默认的 IMiddlewareFactory 实现(即 MiddlewareFactory)。