ASP.NET Core 高级(二)【基于工厂的中间件】 比眉伴天荒 2021-06-26 16:06 328阅读 0赞 # [ASP.NET][] Core 中基于工厂的中间件激活 # `IMiddlewareFactory/IMiddleware` 是`中间件`激活的扩展点。 `UseMiddleware` 扩展方法检查中间件的已注册类型是否实现 `IMiddleware`。 如果是,则使用在容器中注册的 `IMiddlewareFactory` 实例来解析 `IMiddleware` 实现,而不使用基于约定的中间件激活逻辑。中间件在应用的服务容器中注册为作用域或瞬态服务。 优点: * 按请求(作用域服务的注入)激活 * 让中间件强类型化 `IMiddleware` 按请求激活,因此作用域服务可以注入到中间件的构造函数中。 示例应用演示了使用以下两种方式激活的中间件: * 约定。 有关使用约定激活中间件的详细信息,请参阅中间件主题。 * `IMiddleware` 实现。 默认的 `MiddlewareFactory` 类可激活中间件。 这两种中间件实现的功能相同,并能记录由查询字符串参数 (key) 提供的值。 中间件使用插入的数据库上下文(作用域服务)将查询字符串值记录在内存中数据库。 ## `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.cs` 的内置容器中: public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddDbContext<AppDbContext>(options => options.UseInMemoryDatabase("InMemoryDb")); services.AddTransient<FactoryActivatedMiddleware>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); } 两个中间件均在 `Configure` 的请求处理管道中注册: public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseConventionalMiddleware(); app.UseFactoryActivatedMiddleware(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); app.UseMvc(); } ## `IMiddlewareFactory` ## `IMiddlewareFactory` 提供中间件的创建方法。 中间件工厂实现在容器中注册为作用域服务。 可在 `Microsoft.AspNetCore.Http` 包中找到默认的 `IMiddlewareFactory` 实现(即 `MiddlewareFactory`)。 [ASP.NET]: http://ASP.NET
还没有评论,来说两句吧...