中间件注册可以除了可以使用Startup之外,还可以选择StartupFilter
中间件注册可以除了可以使用Startup之外,还可以选择StartupFilter
中间件的注册除了可以借助Startup对象(DelegateStartup或者ConventionBasedStartup)来完成之外,也可以利用另一个叫做StartupFilter的对象来实现。所谓的StartupFilter是对所有实现了IStartupFilter接口的类型及其对象的统称。IStartupFilter接口定义了如下一个唯一的方法Configure,该方法的参数next返回的Action<IApplicationBuilder>对象体现了后续StartupFilter和Startup对中间件的注册,而自身对中间件的注册则实现在返回的Action<IApplicationBuilder>对象中。[本文已经同步到《ASP.NET Core框架揭秘》之中]
1: public interface IStartupFilter
2: {
3: Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next);
4: }
我们可以采用服务注册的方式注册多个StartupFilter。具体来说,StartupFilter具有如下两种不同的注册方式,一种是通过调用WebHostBuilder的ConfigureServices方法以服务的形式注册所需的StartupFilter,另一种则是将针对StartupFilter的服务注册实现在启动类的ConfigureServices方法上。
1: //注册方式1
2: new WebHostBuilder()
3: .ConfigureServices(svcs => svcs
4: .AddSingleton<IStartupFilter, Filter1>()
5: .AddSingleton<IStartupFilter, Filter2>())
6: …
7:
8: //注册方式2
9: public class Startup
10: {
11: public void ConfigureServices(IServiceCollection svcs)
12: {
13: svcs.AddSingleton<IStartupFilter,Filter1>()
14: .AddSingleton<IStartupFilter, Filter2>();
15: }
16: }
既然中间件可以同时通过Startup和StartupFilter进行注册,那么通过这两个种方式注册的中间件有何不同吗?其实它们唯一的区别在于StartupFilter注册的中间件会先执行。话句话说,对于由注册中间件构成的管道来说,通过Startup注册的中间件位于通过StartupFilter注册的中间件之后。我们不妨通过一个简单的实例来证实这一点。我们在一个ASP.NET Core控制台应用中定义如下四个中间件类型(Foo、Bar、Baz和Gux),它们针对请求的处理逻辑很简单,就是将自身的类型名称写入请求的响应中。
1: public abstract class MiddlewareBase
2: {
3: private RequestDelegate _next;
4:
5: public MiddlewareBase(RequestDelegate next)
6: {
7: _next = next;
8: }
9: public async Task Invoke(HttpContext context)
10: {
11: await context.Response.WriteAsync($"{this.GetType().Name}=>");
12: await _next(context);
13: }
14: }
15:
16: public class Foo : MiddlewareBase
17: {
18: public Foo(RequestDelegate next) : base(next){}
19: }
20: public class Bar : MiddlewareBase
21: {
22: public Bar(RequestDelegate next) : base(next) {}
23: }
24: public class Baz : MiddlewareBase
25: {
26: public Baz(RequestDelegate next) : base(next) {}
27: }
28: public class Gux : MiddlewareBase
29: {
30: public Gux(RequestDelegate next) : base(next) {}
31: }
接下来我们定义了如下一个泛型的 StartupFilter<TMiddleware>类,这是一个专门用于注册指定类型中间件的StartupFilter,泛型参数代表注册的中间件类型。在实现的Configure方法中,我们将中间件的注册实现在返回的Action<IApplicationBuilder>对象中。
1: public class StartupFilter<TMiddleware> : IStartupFilter
2: {
3: public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
4: {
5: return app=> {
6: app.UseMiddleware<TMiddleware>();
7: next(app);
8: };
9: }
10: }
我们最终编写如下一段简单的程序来启动承载的应用程序。如下面的额代码片段所示,在利用WebHostBuilder创建并启动WebHost之前,我们调用其ConfigureServices方法注册了两个StartupFilter<TMiddleware>对象,它们对应的中间件类型分别为Foo和Bar。在随后调用的Configure方法中,我们又完成了针对中间Baz和Gux的注册。这段程序实际上注册了五个中间件(调用ApplicationBuilder的Run方法可以视为中间件注册)。
1: public class Program
2: {
3: public static void Main()
4: {
5: new WebHostBuilder()
6: .UseKestrel()
7: .ConfigureServices(svcs => svcs
8: .AddSingleton<IStartupFilter>(new StartupFilter<Foo>())
9: .AddSingleton<IStartupFilter>(new StartupFilter<Bar>()))
10: .Configure(app => app
11: .UseMiddleware<Baz>()
12: .UseMiddleware<Gux>()
13: .Run(async context=> await context.Response.WriteAsync("End")))
14: .Build()
15: .Run();
16: }
17: }
我们现在需要确定注册的这五个在进行请求处理过程中的执行顺序。为此我们直接启动这个程序,然后开启浏览器访问默认的监听地址(http://localhost:5000),浏览器会按照如下图所示形式显示出请求在这个五个中间件中的“路由”。浏览器显示的结果清晰地表明通过StartupFilter注册的中间件比通过Startup注册的中间件先执行。对于两个采用相同方式注册的中间件,先被注册的中间会先执行。

中间件注册可以除了可以使用Startup之外,还可以选择StartupFilter的更多相关文章
- 学习ASP.NET Core, 怎能不了解请求处理管道[5]: 中间件注册可以除了可以使用Startup之外,还可以选择StartupFilter
中间件的注册除了可以借助Startup对象(DelegateStartup或者ConventionBasedStartup)来完成之外,也可以利用另一个叫做StartupFilter的对象来实现.所谓 ...
- 终于将rsync-3.1.2配置成功,之外还挖掘了一些新的用法
1.为什么要用rsync: 有两台主机,开始准备做HA,考虑到工作量的问题,最终决定将重要文件进行同步即可. 找了一些同步的工具,rsync得到一致好评,速度快,消耗小等等. 2.接着找资料,最后选用 ...
- 除了 Microsoft Office我们还可以选择哪些软件?
不同的人有不同爱好,不同的人有着不同的人生追求,软件公司也是如此.尽管 Microsoft Office 比之前要便宜得多了,但其按时间累计的完整的安装版本的价格仍然很高,基于对普通用户亦或手头比较紧 ...
- ASP.NET Core框架揭秘(持续更新中…)
之前写了一系列关于.NET Core/ASP.NET Core的文章,但是大都是针对RC版本.到了正式的RTM,很多地方都发生了改变,所以我会将之前发布的文章针对正式版本的.NET Core 1.0进 ...
- ASP.NET Core框架揭秘(持续更新中…)
之前写了一系列关于.NET Core/ASP.NET Core的文章,但是大都是针对RC版本.到了正式的RTM,很多地方都发生了改变,所以我会将之前发布的文章针对正式版本的.NET Core 1.0进 ...
- ASP.NET Core 学习笔记 第二篇 依赖注入
前言 ASP.NET Core 应用在启动过程中会依赖各种组件提供服务,而这些组件会以接口的形式标准化,这些组件这就是我们所说的服务,ASP.NET Core框架建立在一个底层的依赖注入框架之上,它使 ...
- lambda匿名函数透析
lambda匿名函数透析 目录 1 匿名函数的作用... 1 2 匿名函数的格式... 1 3 匿名函数实例代码... 3 1 匿名函数的作用 ...
- spring-第二章-AOP
一,回顾 1.控制反转(IOC) 以前创建对象,由我们自己决定,现在我们把管理对象的声明周期权力交给spring; 2.依赖注入(DI) A对象需要B对象的支持,spring就把B注入给A,那么A就拥 ...
- APP打开(三)—激活率提升20%的思考
激活是APP拉新后的一个重要环节.通常,我们希望用户打开我们的APP之后,能够顺利的被激活,从而留下来成为我们的忠实用户. 激活一词,就跟北斗星指标一样,对每个产品来说都是不一样的.有些APP一旦打开 ...
随机推荐
- 单元测试:TESTNG和powermock的使用
pom文件: <properties> <testng.version>6.8</testng.version> <powermo ...
- swift的arc 是不是有问题?
class Arctest { let name: String = "Arctest" @lazy var ret:() -> String? = { [weak self ...
- RabbitMQ消息队列随笔
本文权当各位看官对RabbitMQ的基本概念以及使用场景有了一定的了解,如果你还对它所知甚少或者只是停留在仅仅是听说过,建议你先看看这篇文章,在对RabbitMQ有了基本认识后,我们正式开启我们的Ra ...
- 开源LTE代码分析
跟踪了一个在将开源组织-OpenLTE(将4G通信网络LTE开源),现将自己梳理整理的一些文档Post出来,请有相同兴趣的朋友指点: 一,系统介绍 OpenLTE是一位Mot的工程师在12年发起的一个 ...
- ExecutorService和CompletionService区别
ExecutorService和CompletionService区别: ExecutorService:一直习惯自己维护一个list保存submit的callable task所返回的Future对 ...
- 功能测试工具Selenium IDE
Selenium IDE:一个专门用于Firefox浏览器的插件,能够录制回放用户在Firefox中的行为,并把所记录的Selenese (Selenium Commands)转化为HTML/Java ...
- François Hollande’s&…
EVER since President François Hollande was elected last May, things have not gone right for him. He ...
- HDU 1532 Drainage Ditches (网络流)
A - Drainage Ditches Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64 ...
- 微信小程序开发之tab导航栏
实现功能: 点击不同的tab导航,筛选数据 UI: js: data:{ navbar: ['半月维保', '季度维保', '半年维保',"年度维保"], //count ...
- 一个基于Tp3.2(thinkphp3.2)的工会管理系统
该系统包括11个模块. 会员管理模块 奖惩管理模块 运动会管理模块 新闻管理模块 文档管理模块 经费管理模块 电子提案管理模块 用户管理模块 权限管理模块 系统管理模块 系统的登录 系统主页 这里只是 ...