- 全球化与本土化
- 性能
- 高级
ASP.NET Core 中基于工厂的中间件激活
作者:Luke Latham
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)。
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.AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }
两个中间件均在 Startup.Configure
的请求处理管道中注册:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); } else { app.UseExceptionHandler("/Error"); } app.UseConventionalMiddleware(); app.UseFactoryActivatedMiddleware(); app.UseStaticFiles(); app.UseMvc(); }
IMiddlewareFactory
IMiddlewareFactory 提供中间件的创建方法。 中间件工厂实现在容器中注册为作用域服务。
可在 Microsoft.AspNetCore.Http 包中找到默认的 IMiddlewareFactory 实现(即 MiddlewareFactory)。