使用 ASP.NET Core 中的第三方容器激活中间件

本文演示如何使用 IMiddlewareFactoryIMiddleware 作为使用第三方容器激活中间件的可扩展点。 有关 IMiddlewareFactoryIMiddleware 的介绍性信息,请参阅 ASP.NET Core 中基于工厂的中间件激活

查看或下载示例代码如何下载

示例应用演示了使用 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)Middleware/MiddlewareExtensions.cs

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

Startup.ConfigureServices 必须执行多项任务:

  • 设置 Simple Injector 容器。
  • 注册工厂和中间件。
  • 使 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 中基于工厂的中间件激活

查看或下载示例代码如何下载

示例应用演示了使用 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)Middleware/MiddlewareExtensions.cs

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

Startup.ConfigureServices 必须执行多项任务:

  • 设置 Simple Injector 容器。
  • 注册工厂和中间件。
  • 使 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();
}

其他资源