如何传递参数给ASP.NET Core的中间件(Middleware)
问题描述
当我们在ASP.NET Core中定义和使用中间件(Middleware)的时候,有什么好的办法可以给中间件传参数吗?
解决方案
在ASP.NET Core项目中添加一个POCO类来传递参数到中间件,例如下面的GreetingOptions类
public class GreetingOptions { public string GreetAt { get; set; } public string GreetTo { get; set; } }
然后添加一个中间件GreetingMiddleware
public class GreetingMiddleware { private readonly RequestDelegate next; private readonly GreetingOptions options; public GreetingMiddleware( RequestDelegate next, GreetingOptions options) { this.next = next; this.options = options; } public async Task Invoke( HttpContext context) { var message = $"Good {this.options.GreetAt} {this.options.GreetTo}"; await context.Response.WriteAsync(message); } }
通过添加一个扩展方法类GreetingMiddlewareExtension,来配置中间件GreetingMiddleware,并传递参数GreetingOptions options
public static class GreetingMiddlewareExtension { public static IApplicationBuilder UseGreeting(this IApplicationBuilder app, GreetingOptions options) { return app.UseMiddleware<GreetingMiddleware>(options); } }
在ASP.NET Core项目中Startup类的Configure方法中,启用GreetingMiddleware中间件,并传递参数到中间件
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseGreeting(new GreetingOptions { GreetAt = "Morning", GreetTo = "Tahir" }); }
通过添加一个扩展方法类GreetingMiddlewareExtension,来配置中间件GreetingMiddleware,并通过委托Action<GreetingOptions> configureOptions来传递参数GreetingOptions
public static class GreetingMiddlewareExtension { public static IApplicationBuilder UseGreeting(this IApplicationBuilder app, Action<GreetingOptions> configureOptions) { var options = new GreetingOptions(); configureOptions(options); return app.UseMiddleware<GreetingMiddleware>(options); } }
在ASP.NET Core项目中Startup类的Configure方法中,启用GreetingMiddleware中间件,并通过委托Action<GreetingOptions>传递参数到中间件
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseGreeting(options => { options.GreetAt = "Morning"; options.GreetTo = "Tahir"; }); }
讨论
在前面的一篇文章中我们讨论了,定义和使用中间件(Middleware)的最好方法是,将中间件定义在一个单独的类中,然后通过扩展方法将其添加到ASP.NET Core的中间件管道(pipeline)中。
我们可以通过上面介绍的解决方案A和B,将需要传递到中间件的参数都封装为一个POCO类,并创建一个扩展方法,用下面两种方式作为扩展方法的参数:
注意:POCO实例是通过. UseMiddleware()方法的params object[]参数来传递到中间件的构造函数中的,也就是说我们可以通过params object[]来传递任意多个参数到中间件中,只要类型和中间件的构造函数参数匹配即可。我们还可以将依赖注入参数和POCO实例参数一起定义在中间件的构造函数中,如下所示:
public class GreetingMiddleware { private readonly RequestDelegate next; private readonly GreetingOptions options; //IHostingEnvironment env是依赖注入参数,GreetingOptions options是POCO实例参数 public GreetingMiddleware(RequestDelegate next, IHostingEnvironment env, GreetingOptions options) { string environmentName = env.EnvironmentName; this.next = next; this.options = options; } public async Task Invoke( HttpContext context) { var message = $"Good {this.options.GreetAt} {this.options.GreetTo}"; await context.Response.WriteAsync(message); } }
配置依赖注入服务
前面介绍的两种解决方案同样也可以用来配置依赖注入(dependency injection)服务的容器。
为了演示,我们先添加一个POCO类MessageOptions和用到的枚举MessageFormat
public enum MessageFormat { None, Upper, Lower } public class MessageOptions { public MessageFormat Format { get; set; } }
然后添加一个依赖注入接口IMessageService,及其实现类MessageService
public interface IMessageService { string FormatMessage(string message); }
public class MessageService : IMessageService { private readonly MessageOptions options; public MessageService(MessageOptions options) { this.options = options; } public string FormatMessage(string message) { // use options return this.options.Format == MessageFormat.None ? message : this.options.Format == MessageFormat.Upper ? message.ToUpper() : message.ToLower(); } }
同样,接下来我们就用两种解决方案,来定义MessageService的扩展方法类MessageServiceExtension
解决方案A:实例类型(Instance Type)
public static class MessageServiceExtension { // Instance Type public static IServiceCollection AddMessageFormatter(this IServiceCollection services, MessageOptions options) { return services.AddScoped<IMessageService>(factory => { return new MessageService(options); }); } }
在ASP.NET Core项目中Startup类的ConfigureServices方法中,注册IMessageService和MessageService的依赖注入服务
// Instance Type public void ConfigureServices(IServiceCollection services) { services.AddMessageFormatter(new MessageOptions { Format = MessageFormat.Lower }); }
解决方案B:方法类型(Function Type)
public static class MessageServiceExtension { // Function Type public static IServiceCollection AddMessageFormatter(this IServiceCollection services, Action<MessageOptions> configureOptions) { var options = new MessageOptions(); configureOptions(options); return services.AddScoped<IMessageService>(factory => { return new MessageService(options); }); } }
在ASP.NET Core项目中Startup类的ConfigureServices方法中,注册IMessageService和MessageService的依赖注入服务
// Function Type public void ConfigureServices(IServiceCollection services) { services.AddMessageFormatter(options => { options.Format = MessageFormat.Lower; }); }
本文参考自:Passing Parameters to Middleware in ASP.NET Core 2.0
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2018-02-01 SQLServer中DataLength()和Len()两内置函数的区别(转载)