在 ASP.NET Core 中以協力廠商容器啟用中介軟體Middleware activation with a third-party container in ASP.NET Core

作者:Luke LathamBy Luke Latham

本文示範如何使用 IMiddlewareFactoryIMiddleware,作為以協力廠商容器啟動中介軟體的擴充點。This article demonstrates how to use IMiddlewareFactory and IMiddleware as an extensibility point for middleware activation with a third-party container. 如需 IMiddlewareFactoryIMiddleware 的簡介資訊,請參閱 Factory 中介軟體啟用主題。For introductory information on IMiddlewareFactory and IMiddleware, see the Factory-based middleware activation topic.

檢視或下載範例程式碼 (英文) (如何下載)View or download sample code (how to download)

範例應用程式會示範如何透過 IMiddlewareFactory 的實作 SimpleInjectorMiddlewareFactory 來啟用中介軟體。The sample app demonstrates middleware activation by an IMiddlewareFactory implementation, SimpleInjectorMiddlewareFactory. 此範例會使用 Simple Injector 相依性插入 (DI) 容器。The sample uses the Simple Injector dependency injection (DI) container.

範例的中介軟體實作會記錄查詢字串參數 (key) 所提供的值。The sample's middleware implementation records the value provided by a query string parameter (key). 中介軟體會使用插入的資料庫內容 (範圍服務),以記錄記憶體內部資料庫的查詢字串值。The middleware uses an injected database context (a scoped service) to record the query string value in an in-memory database.

注意

範例應用程式純粹基於示範目的使用 Simple InjectorThe sample app uses Simple Injector purely for demonstration purposes. 使用 Simple Injector 並不表示為其背書。Use of Simple Injector isn't an endorsement. Simple Injector 文件和 GitHub 問題中所述的中介軟體啟用方法是 Simple Injector 維護人員建議使用的方法。Middleware activation approaches described in the Simple Injector documentation and GitHub issues are recommended by the maintainers of Simple Injector. 如需詳細資訊,請參閱 Simple Injector documentation (Simple Injector 文件) 和 Simple Injector GitHub repository (Simple Injector GitHub 存放庫)。For more information, see the Simple Injector documentation and Simple Injector GitHub repository.

IMiddlewareFactoryIMiddlewareFactory

IMiddlewareFactory 可提供建立中介軟體的方法。IMiddlewareFactory provides methods to create middleware.

在範例應用程式中,將實作中介軟體 Factory 來建立 SimpleInjectorActivatedMiddleware 執行個體。In the sample app, a middleware factory is implemented to create an SimpleInjectorActivatedMiddleware instance. 中介軟體 Factory 會使用 Simple Injector 容器來解析中介軟體:The middleware factory uses the Simple Injector container to resolve the middleware:

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.
    }
}

IMiddlewareIMiddleware

IMiddleware 可定義應用程式要求管線的中介軟體。IMiddleware defines middleware for the app's request pipeline.

IMiddlewareFactory 實作啟動的中介軟體 (Middleware/SimpleInjectorActivatedMiddleware.cs):Middleware activated by an IMiddlewareFactory implementation (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):An extension is created for the middleware (Middleware/MiddlewareExtensions.cs):

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

Startup.ConfigureServices 必須執行幾項工作:Startup.ConfigureServices must perform several tasks:

  • 設定 Simple Injector 容器。Set up the Simple Injector container.
  • 註冊 Factory 和中介軟體。Register the factory and middleware.
  • 讓應用程式的資料庫內容可從 Razor 頁面的 Simple Injector 容器使用。Make the app's database context available from the Simple Injector container for a Razor Page.
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 中註冊:The middleware is registered in the request processing pipeline in 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();
}

其他資源Additional resources