.NET Core中的IStartupFilter

本文详细解析Startup中如何配置中间件,IApplicationBuilder的作用以及IStartupFilter接口的应用,展示了自定义中间件和IStartupFilter如何延长请求管道生命周期的过程。
摘要由CSDN通过智能技术生成

Startup中配置中间件请求管道,通常是这样的:

public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles();
    app.UseMvc(routes => {
        routes.MapRoute(
            name : "default",
            template: "{controller=Home}/{action=Index}/{id}"
        );
    });
}

看看IStartupFilter

namespace Micorosft.AspNetCore.Hosting
{
    public interface IStartupFilter
    {
        Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next);
    }
}

IStartupFilter接受一个泛型委托,生成一个泛型委托。

联想到,Startup有一个实例方法,也返回泛型委托。

Startup _startup = new Startup();
Action<IApplicationBuilder> startupConfiture =  _startup.Configure;

这里的startupConfiture是可以给IStartupFilterConfigure方法的。

IStartupFilter filter1 = new StartupFilter();
Action<IApplicationBuilder> filterConfigure = filter1.Configure(startupConfigure);
IStartupFilter filter2 = new StartupFilter();
Action<IApplicationBuilder> filterConfigure2 = filter2.Configure(filterConfigure);

也就是说,从请求管道出来,通过IStartupFilterIApplicationBuilder的生命延长了。

也可以这么理解,实际上,请求管道里的东东都实现了IStartupFilter这个接口。

那么,IApplicationBuilder是什么时候被调用的呢?是生成WebHost的时候调用。

public static void Main(string[] args)
{
    var host = new WebHostBuilder()
        .UseKestrel()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseStartup<Startup>()
        .Build();
    host.Run();
}

来看看Build方法内部。

private RequestDelegate BuildApplication()
{
    //工厂的方式生成IApplicationBuilder
    IApplicationBuilder builder = builderFactory.CreateBuilder(Server.Features);
    builder.ApplicationService = _applicationServices;
    //从DI容器中取出服务
    var startupFilters = _applicationServices.GetService<IEnumerable<IStartupFilter>>();
    //一下,Startup中的Configure是对于请求管道而言的
    Action<IApplicationBuilder> configure = _startup.Configure();
    foreach(var filter in startupFilters.Reverse())
    {
        configure = filter.Configure(configure);
    }
    conigure(builder);
    return builder.Build();//RequestDelegate就是请求管道本身
}

举个例子

自定义一个中间件。

public class RequestServiceContainerMiddleware
{
    private readonly RequestDelegate _next;
    private IServiceScopeFactory _scopeFactory;
    public RequestServiceContainerMiddleware(RequestDelegate next, IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
        _next = next;
    }
    public async Task Invoke(HttpContext httpContext)
    {
        var existingFeatures = httpContext.Features.Get<IServiceProvidersFeature>();
        if(existingFeatures?.RequestService!=null)
        {
            await _next.Invoke(httpContext);
            return;
        }
        using(var feature = new RequestServiceFeature(_scopeFactory))
        {
            try
            {
                httpContext.Feature.Set<IServiceProviderFactory>(feature);
                await _next.Invoke(httpContext);
            }
            catch{}
        }
    }
}

自定义IStartupFilter

public class AutoRequestServiceStartupFilter : IStartupFilter
{
    public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
    {
        return builder => {
            builder.UseMiddleware<RequestServiceContainerMiddlware>();
            next(builder);
        };
    }
}

AutoRequestServiceStartupFilter无需注册,因为在Build方法的时候就已经调用了所有实现IStartupFilter接口的类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值