在 ASP.NET Core 中以協力廠商容器啟用中介軟體

此文章示範如何使用 IMiddlewareFactoryIMiddleware 作為以協力廠商容器啟用中介軟體的擴充點。 如需 IMiddlewareFactoryIMiddleware 的簡介資訊,請參閱在 ASP.NET Core 中以 Factory 為基礎的中介軟體啟用

檢視或下載範例程式碼 \(英文\) (如何下載)

範例應用程式會示範如何透過 IMiddlewareFactory 的實作 SimpleInjectorMiddlewareFactory 來啟用中介軟體。 此範例會使用 Simple Injector 相依性插入 (DI) 容器。

範例的中介軟體實作會記錄查詢字串參數 (key) 所提供的值。 中介軟體會使用插入的資料庫內容 (範圍服務),以記錄記憶體內部資料庫的查詢字串值。

注意

範例應用程式純粹基於示範目的使用 Simple Injector。 使用 Simple Injector 並不表示為其背書。 Simple Injector 文件和 GitHub 問題中所述的中介軟體啟用方法是 Simple Injector 維護人員建議使用的方法。 如需詳細資訊,請參閱 Simple Injector documentation (Simple Injector 文件) 和 Simple Injector GitHub repository (Simple Injector GitHub 存放庫)。

IMiddlewareFactory

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

在範例應用程式中,將實作中介軟體 Factory 來建立 SimpleInjectorActivatedMiddleware 執行個體。 中介軟體 Factory 會使用 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 容器。
  • 註冊 Factory 和中介軟體。
  • 讓應用程式的資料庫內容可從 Simple Injector 容器使用。
public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    // 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, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseSimpleInjectorActivatedMiddleware();

    app.UseStaticFiles();
    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

此文章示範如何使用 IMiddlewareFactoryIMiddleware 作為以協力廠商容器啟用中介軟體的擴充點。 如需 IMiddlewareFactoryIMiddleware 的簡介資訊,請參閱在 ASP.NET Core 中以 Factory 為基礎的中介軟體啟用

檢視或下載範例程式碼 \(英文\) (如何下載)

範例應用程式會示範如何透過 IMiddlewareFactory 的實作 SimpleInjectorMiddlewareFactory 來啟用中介軟體。 此範例會使用 Simple Injector 相依性插入 (DI) 容器。

範例的中介軟體實作會記錄查詢字串參數 (key) 所提供的值。 中介軟體會使用插入的資料庫內容 (範圍服務),以記錄記憶體內部資料庫的查詢字串值。

注意

範例應用程式純粹基於示範目的使用 Simple Injector。 使用 Simple Injector 並不表示為其背書。 Simple Injector 文件和 GitHub 問題中所述的中介軟體啟用方法是 Simple Injector 維護人員建議使用的方法。 如需詳細資訊,請參閱 Simple Injector documentation (Simple Injector 文件) 和 Simple Injector GitHub repository (Simple Injector GitHub 存放庫)。

IMiddlewareFactory

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

在範例應用程式中,將實作中介軟體 Factory 來建立 SimpleInjectorActivatedMiddleware 執行個體。 中介軟體 Factory 會使用 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 容器。
  • 註冊 Factory 和中介軟體。
  • 讓應用程式的資料庫內容可從 Simple Injector 容器使用。
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    // 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.UseSimpleInjectorActivatedMiddleware();

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

其他資源