ASP.NET Core 高階(二)【基於工廠的中介軟體】

風靈使發表於2019-02-20

ASP.NET Core 中基於工廠的中介軟體啟用

IMiddlewareFactory/IMiddleware中介軟體啟用的擴充套件點。

UseMiddleware 擴充套件方法檢查中介軟體的已註冊型別是否實現 IMiddleware。 如果是,則使用在容器中註冊的 IMiddlewareFactory 例項來解析 IMiddleware 實現,而不使用基於約定的中介軟體啟用邏輯。中介軟體在應用的服務容器中註冊為作用域或瞬態服務。

優點:

  • 按請求(作用域服務的注入)啟用
  • 讓中介軟體強型別化

IMiddleware 按請求啟用,因此作用域服務可以注入到中介軟體的建構函式中。

示例應用演示了使用以下兩種方式啟用的中介軟體:

  • 約定。 有關使用約定啟用中介軟體的詳細資訊,請參閱中介軟體主題。
  • IMiddleware 實現。 預設的 MiddlewareFactory 類可啟用中介軟體。

這兩種中介軟體實現的功能相同,並能記錄由查詢字串引數 (key) 提供的值。 中介軟體使用插入的資料庫上下文(作用域服務)將查詢字串值記錄在記憶體中資料庫。

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.cs 的內建容器中:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<AppDbContext>(options =>
        options.UseInMemoryDatabase("InMemoryDb"));

    services.AddTransient<FactoryActivatedMiddleware>();

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

兩個中介軟體均在 Configure 的請求處理管道中註冊:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseConventionalMiddleware();
    app.UseFactoryActivatedMiddleware();

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseMvc();
}

IMiddlewareFactory

IMiddlewareFactory 提供中介軟體的建立方法。 中介軟體工廠實現在容器中註冊為作用域服務。

可在 Microsoft.AspNetCore.Http 包中找到預設的 IMiddlewareFactory 實現(即 MiddlewareFactory)。

相關文章