ASP.NET Core 高階(三)【使用第三方容器的基於工廠的中介軟體】

風靈使發表於2019-02-20

使用 ASP.NET Core 中的第三方容器啟用中介軟體

本文演示如何使用 IMiddlewareFactoryIMiddleware 作為使用第三方容器啟用中介軟體的可擴充套件點。 有關 IMiddlewareFactoryIMiddleware 的介紹性資訊,請參閱基於工廠的中介軟體啟用主題。

示例應用演示了使用 IMiddlewareFactorySimpleInjectorMiddlewareFactory 實現啟用的中介軟體。 此示例使用 Simple Injector 依賴項注入 (DI) 容器。

此示例的中介軟體實現記錄了查詢字串引數 (key) 提供的值。 中介軟體使用插入的資料庫上下文(有作用域的服務)將查詢字串值記錄在記憶體中資料庫。

此示例應用僅出於演示目的使用 Simple Injector。 不認可使用 Simple Injector。 Simple Injector 文件中描述的中介軟體啟用方法和 Simple Injector 維護人員推薦的 GitHub 問題。 有關詳細資訊,請參閱 Simple Injector 文件和 Simple Injector GitHub 儲存庫。

IMiddlewareFactory

IMiddlewareFactory 提供中介軟體的建立方法。

在示例應用中,實現了中介軟體工廠以建立 SimpleInjectorActivatedMiddleware 例項。 中介軟體工廠使用 Simple Injector 容器來解析中介軟體:

public class SimpleInjectorMiddlewareFactory : IMiddlewareFactory
{
    private readonly Container _container;

    public SimpleInjectorMiddlewareFactory(Container container)
    {
        _container = container;
    }

    public IMiddleware Create(Type middlewareType)
    {
        return _container.GetInstance(middlewareType) as IMiddleware;
    }

    public void Release(IMiddleware middleware)
    {
        // The container is responsible for releasing resources.
    }
}

IMiddleware

IMiddleware 定義應用的請求管道的中介軟體。

IMiddlewareFactory 實現 (Middleware/SimpleInjectorActivatedMiddleware.cs) 啟用的中介軟體:

public class SimpleInjectorActivatedMiddleware : IMiddleware
{
    private readonly AppDbContext _db;

    public SimpleInjectorActivatedMiddleware(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 = "SimpleInjectorActivatedMiddleware", 
                    Value = keyValue
                });

            await _db.SaveChangesAsync();
        }

        await next(context);
    }
}

為中介軟體建立擴充套件 (Middleware/MiddlewareExtensions.cs):

public static class MiddlewareExtensions
{
    public static IApplicationBuilder UseSimpleInjectorActivatedMiddleware(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<SimpleInjectorActivatedMiddleware>();
    }
}

Startup.ConfigureServices 必須執行多項任務:

  • 設定 Simple Injector 容器。
  • 註冊工廠和中介軟體。
  • Razor 頁面的 Simple Injector 容器建立應用的資料庫上下文。
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

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

    // Replace the default middleware factory with the 
    // SimpleInjectorMiddlewareFactory.
    services.AddTransient<IMiddlewareFactory>(_ =>
    {
        return new SimpleInjectorMiddlewareFactory(_container);
    });

    // Wrap ASP.NET Core requests in a Simple Injector execution 
    // context.
    services.UseSimpleInjectorAspNetRequestScoping(_container);

    // Provide the database context from the Simple 
    // Injector container whenever it's requested from 
    // the default service container.
    services.AddScoped<AppDbContext>(provider => 
        _container.GetInstance<AppDbContext>());

    _container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

    _container.Register<AppDbContext>(() => 
    {
        var optionsBuilder = new DbContextOptionsBuilder<DbContext>();
        optionsBuilder.UseInMemoryDatabase("InMemoryDb");
        return new AppDbContext(optionsBuilder.Options);
    }, Lifestyle.Scoped);

    _container.Register<SimpleInjectorActivatedMiddleware>();

    _container.Verify();
}

中介軟體在 Startup.Configure 的請求處理管道中註冊:

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

    app.UseSimpleInjectorActivatedMiddleware();

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

相關文章