我开发了一块ASP.NET Core中间件。我在这篇文章中简化了中间件,以使问题更加清晰。
中间件在Startup.cs
中配置如下:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseMyMiddleware(42);
...
}
整数(42
)存储在中间件实例中,一切都很好。
现在我想创建一些辅助方法作为扩展方法:
public static int Add(this int i)
{
return i + TODO;
}
我希望该方法将i
的值添加到发送到中间件的值(42
)。
目前我已将42
的值保存在中间件内的公共静态var中,并通过我的扩展方法访问它:
public static int Add(this int i)
{
return i + MyMiddleware.Value;
}
由于种种原因,我不喜欢这种解决方案。任何关于如何以更好的方式解决这个问题的想法都将受到高度赞赏。
答案 0 :(得分:1)
通常,这不适用于扩展方法。扩展方法是静态的,因此只能访问其他静态成员。但是,ASP.NET Core by design 不使用任何静态,并广泛使用dependency injection来管理对象的生命周期和访问依赖项。
通常,正确的方法是将扩展方法移动到某种非静态辅助对象中,然后可以在需要访问它的地方注入它。当然,这不允许您在任何需要的地方轻松调用它,但需要显式依赖它(这是依赖注入点之一)。
话虽如此,你的明确案例有点不同。正如我在linked pull request中看到的那样,您的扩展方法看起来像这样(注意,我在这里结合了两种方法来说明这一点):
public static async Task ShipAsync(this Exception exception, HttpContext context)
{
await MessageShipper.ShipAsync(
ElmahIoMiddleware.ApiKey.AssertApiKeyInMiddleware(),
ElmahIoMiddleware.LogId.AssertLogIdInMiddleware(),
exception.Message, context, new ElmahIoSettings(), exception);
}
为什么重要?因为您正在通过HttpContext
。 HTTP上下文使我们可以访问依赖注入。所以我们实际上可以从依赖注入容器中解决问题:
public static async Task ShipAsync(this Exception exception, HttpContext context)
{
var elmahIoConfig = context.RequestServices.GetService<ElmahIoConfiguration>();
await MessageShipper.ShipAsync(
elmahIoConfig.ApiKey,
elmahIoConfig.LogId,
exception.Message, context, new ElmahIoSettings(), exception);
}
现在,您只需要确保在注册中间件时ElmahIoConfiguration
正确填充。请注意,我不是在这里请求中间件实例,因为中间件通常没有注册依赖注入。引入一个单独的对象更有意义,然后可以将其注入中间件并在那里进行初始化。
在您的情况下,您应该将中间件配置真正移动到您的应用程序设置中,并使用IOptions<>
模式在ConfigureServices
级别配置它。将中间件添加到Configure
中的管道中时配置中间件实际上不再是ASP.NET Core 2中的常见模式。
答案 1 :(得分:0)
为什么不使用appsettings.json存储此信息,然后使用内置的DI将其注入中间件?
<强> appsettings.json 强>
{
"MiddlewareConfiguration":
{
"MiddlewareValue":42,
}
}
<强> Startup.cs 强>
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.Configure<MiddlewareConfiguration>(configuration.GetSection("MiddlewareConfiguration"));
}
<强> MiddlewareConfiguration.cs 强>
public class MiddlewareConfiguration
{
public int MiddlewareValue { get; set; }
}
然后您可以将其注入中间件,例如:
public async Task Invoke(HttpContext context, IOptions<MiddlewareConfiguration> config)