原文:Exploring IStartupFilter in ASP.NET Core
作者:Andrew Lock
译者:Lamond Lu

在本篇博客中,我将介绍一下IStartupFilter, 以及如何在ASP.NET Core中使用它。在下一篇博客中,我将介绍一下如何在外部中间件中使用IStartupFilter

IStartupFilter接口

IStartupFilter接口存在于Microsoft.AspNetCore.Hosting.Abstractions程序集中,它非常简单,仅定义了一个接口方法。

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

其中Configure方法返回了一个变量Action

当创建一个ASP.NET Core应用程序的时候,IApplicationBuilder负责配置ASP.NET Core的中间件管道。例如你可以在Startup.cs文件的Configure方法中,看到以下类似的代码。

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

在这个方法中,你可以直接使用方法提供的IApplicationBuilder参数,并且可以向其中添加各种中间件。使用IStartupFilter, 你可以指定并返回一个Action类型的泛型委托,这意味你除了可以使用方法提供的泛型委托配置IApplicationBuilder对象, 还需要返回一个泛型委托。

IStartupFilter方法可以接受一个配置IApplicationBuilder的方法,换而言之IStartupFilter.Configure方法可以使用Startup.Configure方法作为参数。

例:

Startup _startup = new Startup();
Action<IApplicationBuilder> startupConfigure = _startup.Configure;//后续会补充StartupFilter1类的代码
IStartupFilter filter1 = new StartupFilter1(); Action<IApplicationBuilder> filter1Configure = filter1.Configure(startupConfigure)//后续会补充StartupFilter2类的代码
IStartupFilter filter2 = new StartupFilter2(); Action<IApplicationBuilder> filter2Configure = filter2.Configure(filter1Configure)

如果之前你学习过ASP.NET Core的中间件管道,对于这个代码,你可能会感觉很熟悉。这里我们正在建立另一条管道, 它是一个Configure方法的管道,而不是中间件管道。 这就是IStartupFilter的目的,允许在应用程序中创建Configure方法的管道。

实现IStartupFilter接口的对象何时会被调用?

现在我们对IStartupFilter的签名有了更进一步的理解,接下来我们可以看看它在ASP.NET Core框架中的用法。

要查看IStartupFilter是如果被调用的,你可以在查看Microsoft.AspNetCore.Hosting程序集中的WebHost类。 当你在WebHostBuilder对象上调用Build方法时,实现IStartupFilter接口对象会被调用。 这个代码通常出现在Program.cs文件中,例如:

public class Program
{public static void Main(string[] args){var host = new WebHostBuilder().UseKestrel()    .UseContentRoot(Directory.GetCurrentDirectory()).UseStartup<Startup>().Build();  // 这个会调用BuildApplication方法host.Run(); }
}

下面是BuildApplication方法的部分代码,你可以看到这个方法负责初始化中间件管道。方法的返回值RequestDelegate表示了一个完整的管道,当请求到达的时候,Kestral服务器可以调用它。

private RequestDelegate BuildApplication()
{..IApplicationBuilder builder = builderFactory.CreateBuilder(Server.Features);builder.ApplicationServices = _applicationServices;var startupFilters = _applicationServices.GetService<IEnumerable<IStartupFilter>>();Action<IApplicationBuilder> configure = _startup.Configure;foreach (var filter in startupFilters.Reverse()){configure = filter.Configure(configure);}configure(builder);return builder.Build();
}

首先,此方法创建IApplicationBuilder的实例,该实例将用于构建中间件管道,并将ApplicationServices设置为已配置的DI容器。

接下来的代码块很意思。首先,从DI容器中获取了一个集合IEnumerable<IStartupFilter。正如我前面说的那样,我们可以配置多个IStartupFilter来形成一个管道,所以这个方法只是从容器中取出它们。此外,Startup.Configure方法被保存到局部变量configure中, 这就是通常在Startup类中编写的Configure方法,用于配置中间件管道。

现在我们通过循环遍历每个IStartupFilter(以相反的顺序),传入Startup.Configure方法,然后更新局部变量configure来创建Configure方法的管道。这种方式实现了一种嵌套管道的效果。例如,如果我们有三个IStartupFilter实例,你最终会得到类似这样的东西,其中内部Configure方法在参数中传递给外部方法:

局部变量configure的最终值会被IApplicationBuilder调用来执行实际的中间件管道配置。 调用builder.Build方法之后会生成处理HTTP请求所需的RequestDelegate

一个IStartupFilter的例子

前面我虽然描述了IStartupFilter的用途,但是可能查看一些现成的实现会更容易理解一些。 默认情况下,WebHostBuilder在初始化时会注册一个IStartupFilter - AutoRequestServicesStartupFilter

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

本质上,它在中间件管道的开头添加了一个额外的中间件,即RequestServicesContainerMiddleware

这是唯一一个默认注册的IStartupFilter,因此在这种情况下,参数next将是Startup类的Configure方法。

这基本上就是IStartupFilter的全部内容 - 它是一种在配置的管道的开头或结尾添加额外中间件(或其他配置)的方法。

如何注册IStartupFilter

注册IStartupFilter很简单,只需像往常一样在你的ConfigureServices方法中注册它。 默认情况下,在WebHostBuilder中已经注册了AutoRequestServicesStartupFilter

private IServiceCollection BuildHostingServices()
{...services.AddTransient<IStartupFilter, AutoRequestServicesStartupFilter>();...
}

RequestServicesContainerMiddleware中间件

以下是RequestServicesContainerMiddleware的部分代码

public class RequestServicesContainerMiddleware
{private readonly RequestDelegate _next;private IServiceScopeFactory _scopeFactory;public RequestServicesContainerMiddleware(RequestDelegate next, IServiceScopeFactory scopeFactory){_scopeFactory = scopeFactory;_next = next;}public async Task Invoke(HttpContext httpContext){var existingFeature = httpContext.Features.Get<IServiceProvidersFeature>();if (existingFeature?.RequestServices != null){await _next.Invoke(httpContext);return;}using (var feature = new RequestServicesFeature(_scopeFactory)){try{httpContext.Features.Set<IServiceProvidersFeature>(feature);await _next.Invoke(httpContext);}finally{httpContext.Features.Set(existingFeature);}}}
}

该中间件负责设置IServiceProvidersFeature。 创建时,RequestServicesFeature为请求创建新的IServiceScopeIServiceProvider。 它将负责使用Scoped生命周期添加到DI容器的依赖项的创建和处理。

IStartupFilter的使用场景

一般来说,我不认为在用户的应用程序中需要使用IStartupFilter。 就其本质而言,用户可以在Configure方法中定义中间件管道,因此IStartupFilter是不必要的。

我能想到以下几种需要使用IStartupFilter的场景:

  • 你自己创建了一个库,你需要确保你的中间件在中间件管道的开头(或结尾)运行。
  • 你正在使用一个使用IStartupFilter的库,您需要确保您的中间件在它之前运行。

总结

本篇博文中,我讲解了IStartupFilter以及WebHost如何使用它在构建中间件管道。 在下一篇文章中,我将探讨IStartupFilter的具体用法。

后记

本篇是作者早期的一篇博文,个人觉着对IStartupFilter讲解的比较清楚,就翻译了一下。在作者的后期博文中,作者提供了许多IStartupFilter的使用场景,例如

  • 在ASP.NET Core项目启动前,使用IStartupFilter验证强类型配置
  • 在ASP.NET Core项目启动前,使用IStartupFilter进行数据库迁移和缓存预读取

有兴趣的同学可以自己阅读一下,后续我会选择一些有意思的文章翻译一下。

转载于:https://www.cnblogs.com/lwqlun/p/10279874.html

探索ASP.NET Core中的IStartupFilter相关推荐

  1. 如何在ASP.Net Core中使用Glimpse

    Glimpse是一种流行的开源Web调试和诊断工具,可用于获取ASP.Net或ASP.Net MVC应用程序性能的可见性. 您还可以将Glimpse与Application Insights集成. G ...

  2. glimpse .net_如何在ASP.Net Core中使用Glimpse

    glimpse .net Glimpse是一种流行的开源Web调试和诊断工具,可用于获取ASP.Net或ASP.Net MVC应用程序的性能的可见性. 您还可以将Glimpse与Application ...

  3. 如何使用C#在ASP.NET Core中轻松实现QRCoder

    by Yogi 由瑜伽士 如何使用C#在ASP.NET Core中轻松实现QRCoder (How to easily implement QRCoder in ASP.NET Core using ...

  4. asp.net core中IHttpContextAccessor和HttpContextAccessor的妙用

    分享一篇文章,关于asp.net core中httpcontext的拓展. 现在,试图围绕HttpContext.Current构建你的代码真的不是一个好主意,但是我想如果你正在迁移一个企业类型的应用 ...

  5. 在asp.net core中使用托管服务实现后台任务

    在业务场景中经常需要后台服务不停的或定时处理一些任务,这些任务是不需要及时响应请求的. 在 asp.net中会使用windows服务来处理. 在 asp.net core中,可以使用托管服务来实现,托 ...

  6. ASP.NET Core中显示自定义错误页面-增强版

    之前的博文 ASP.NET Core中显示自定义错误页面 中的方法是在项目中硬编码实现的,当有多个项目时,就会造成不同项目之间的重复代码,不可取. 在这篇博文中改用middleware实现,并且放在独 ...

  7. 如何简单的在 ASP.NET Core 中集成 JWT 认证?

    前情提要:ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统 文章超长预警(1万字以上),不想看全部实现过程的同学可以直接跳转到末尾查看成果或者一键安装相关的 nuget 包 自上一 ...

  8. 在 ASP.NET Core 中集成 Skywalking APM

    前言 大家好,今天给大家介绍一下如何在 ASP.NET Core 项目中集成 Skywalking,Skywalking 是 Apache 基金会下面的一个开源 APM 项目,有些同学可能会 APM ...

  9. .ASP NET Core中缓存问题案例

    本篇博客中,我将描述一个关于会话状态(Session State)的问题, 这个问题我已经被询问了好几次了. 问题的场景 创建一个新的ASP.NET Core应用程序 一个用户在会话状态中设置了一个字 ...

最新文章

  1. (13)处理静态资源(自定义资源映射)【从零开始学Spring Boot】
  2. 手握6亿把钥匙 能否打开“智能家居”的大门?
  3. 用python让excel飞起来 pdf_能听会写的科大讯飞智能办公本,让工作效率瞬间翻番!丨试用...
  4. iOS手势UIGustureRecognizer
  5. 售票系统的组件图和部署图_实物图+电气图讲解:教你学会看配电系统图,值得收藏!...
  6. 使用Nativefier将web页面打包为桌面应用
  7. 电化学稳态阻抗谱(EIS)在等效电路已知的情况下进行拟合,python第三方工具包impedance.py
  8. 5种设计有效按钮的最佳做法
  9. 云原生的高效生产工具 ---vagrant
  10. gmail邮箱注册成功流程
  11. 为了让你在“口袋奇兵”聊遍全球,手撕ArrayList底层,透彻分析源码
  12. 翻译:软件测试的未来五个趋势
  13. Spring Boot启动参考指南(官方版)
  14. Windows 10环境下TensorFlow(gpu版本)配置教程——[图解] [详细版][零基础]
  15. jquery 实现购物车的商品总数及价格计算
  16. 计算机网络正常无法打开网页,电脑网络正常但是网页无法打开怎么样解决
  17. Nginx 基本理论和安装
  18. vue3的自定义指令directives
  19. python nose
  20. Catalan (卡特兰数)

热门文章

  1. docker run指定entrypiont
  2. 【原创视频】docker pull和docker run运行原理分析
  3. k8s修改端口访问:nodeport暴露的端口范围修改
  4. ubuntu18.04安装openresty
  5. Scala 类中声明方法
  6. python3猜数字小游戏代码示例
  7. vuetify框架中服务端分页的实现方式(指定初始显示记录数)
  8. IDEA使用自带数据库连接工具连接Mysql,及报错解决
  9. 解决Win10不能访问共享文件夹的问题
  10. 快速了解 UML 类图