簡體   English   中英

在ASP.NET Core中使用擴展方法中的中間件配置

[英]Using middleware config from extension methods in ASP.NET Core

我已經開發了一個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保存在中間件內部的公共static var中,並通過我的擴展方法進行訪問:

public static int Add(this int i)
{
    return i + MyMiddleware.Value;
}

由於種種原因,我不喜歡這種解決方案。 如何更好地解決此問題的任何想法將受到高度贊賞。

通常,這不適用於擴展方法。 擴展方法是靜態的,因此只能訪問其他靜態成員。 但是 ASP.NET Core 在設計上不使用任何靜態變量,並且廣泛使用依賴項注入來管理對象的生存期和訪問依賴項。

因此,通常,正確的方法是將擴展方法移到某種非靜態幫助器對象中,然后可以將其插入需要訪問它的位置。 當然,這將不允許您在需要的地方輕松調用它,而需要您明確依賴它(這是依賴注入的要點之一)。

話雖如此,您的明確情況有些不同。 鏈接的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級別對其進行ConfigureServices 在ASP.NET Core 2中將中間件添加到“ Configure的管道時進行Configure實際上不再是一種常見的模式。

您為什么不使用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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM