我已经开发了一段ASP.NET核心中间件。我在这篇文章中简化了中间件,以使问题变得更清楚。
中间件在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的值,并通过扩展方法访问了这个值:
public static int Add(this int i)
{
return i + MyMiddleware.Value;
}由于种种原因,我不喜欢这个解决方案。对于如何以更好的方式解决这一问题,我们将不胜感激。
发布于 2018-02-05 08:53:04
通常情况下,扩展方法不适用于此。扩展方法是静态的,因此只能访问其他静态成员。然而,ASP.NET核心在设计上不使用任何静力学,并且广泛使用依赖注入来管理对象的生存期和访问依赖项。
因此,通常情况下,正确的方法是将扩展方法移动到某种非静态助手对象中,然后将其注入到需要访问它的位置。当然,这将不允许您在需要时轻松地调用它,而是要求您显式地依赖它(这是依赖注入的点之一)。
话虽如此,你的明确案例有点不同。从您的链接拉请求中可以看到,您的扩展方法如下所示(注意,我在这里合并了两个方法,以表明这一点):
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中的常见模式。
发布于 2018-02-05 08:22:04
为什么不使用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)https://stackoverflow.com/questions/48618160
复制相似问题