ASP.NET Core 中基於工廠的中間件激活


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)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM