在上节中我们已经得知 WebApplication 实现了 IApplicationBuilder,我们浅谈了其pipe特质和构建方法,本节中将深入了解 ApplicationBuilder 以窥探 IApplicationBuilder 真相

public interface IApplicationBuilder
{
IServiceProvider ApplicationServices { get; set; }
IFeatureCollection ServerFeatures { get; }
IDictionary<string, object?> Properties { get; }
IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
IApplicationBuilder New();
RequestDelegate Build();
}

管道机制

​ 该机制是.NET最关键的机制之一,贯彻整个APP生命周期,但他的实现,简单巧妙的让人惊叹。

​ 首先在内部维护了一个 Func<RequestDelegate, RequestDelegate> 集合

private readonly List<Func<RequestDelegate, RequestDelegate>> _components = new List<Func<RequestDelegate, RequestDelegate>>();

Func<RequestDelegate, RequestDelegate> 还有一个美腻的别名叫:中间件,UseMiddleware 的本质,就是 IApplicationBuilder.Use,调用 Use 其实就是添加一个中间件到集合

public IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
{
this._components.Add(middleware);
return (IApplicationBuilder) this;
}

​ 最终在 Build 生成此应用程序用于处理HTTP请求的委托。

public RequestDelegate Build()
{
RequestDelegate requestDelegate = (RequestDelegate) (context =>
{
Endpoint endpoint = context.GetEndpoint();
if (endpoint?.RequestDelegate != null)
throw new InvalidOperationException("The request reached the end of the pipeline without executing the endpoint: '" + endpoint.DisplayName + "'. Please register the EndpointMiddleware using 'IApplicationBuilder.UseEndpoints(...)' if using routing.");
context.Response.StatusCode = 404;
return Task.CompletedTask;
});
for (int index = this._components.Count - 1; index >= 0; --index)
requestDelegate = this._components[index](requestDelegate);
return requestDelegate;
}

​ 为什么要倒着循环呢?这是因为在ASP.NET Core中,中间件的执行顺序是按照它们在ApplicationBuilder中注册的顺序来决定的。后注册的中间件会在前注册的中间件之前执行,这就是经典的洋葱模型

Properties&Features

Properties 是一个字典,用于在中间件之间共享数据。

public IDictionary<string, object?> Properties { get; }

​ 为了防止在中间件中修改 ApplicationBuilder 对象的状态,实现了一个原型模型:仅复制 Properties

public IApplicationBuilder New() => (IApplicationBuilder) new ApplicationBuilder(this);
private ApplicationBuilder(ApplicationBuilder builder) => this.Properties = (IDictionary<string, object>) new CopyOnWriteDictionary<string, object>(builder.Properties, (IEqualityComparer<string>) StringComparer.Ordinal);

Features 用于获取应用程序Server提供的一组HTTP features,如果程序没有指定Server,则返回空集合

public interface IFeatureCollection : IEnumerable<KeyValuePair<Type, object>>, IEnumerable

​ 在 ApplicationBuilderFeatures 直接引用 Properties,他们两者基本等价。而在 WebApplication 中,通过 IServer 提供

IFeatureCollection ServerFeatures => this._host.Services.GetRequiredService<IServer>().Features;

IServer 是服务器知识,看同学们述求,考虑是否讲

IServiceProvider

IServiceProvider 用于访问应用程序服务容器,位于 System 命名空间,在整个 .NET 中举重若轻。它的功能非常简洁,只做一件事情,仅有一个方法,用于从服务容器中获取给定服务的实现

public interface IServiceProvider
{
/// <summary>Gets the service object of the specified type.</summary>
/// <param name="serviceType">An object that specifies the type of service object to get.</param>
/// <returns>A service object of type <paramref name="serviceType" />.
/// -or-
/// <see langword="null" /> if there is no service object of type <paramref name="serviceType" />.</returns>
object? GetService(Type serviceType);
}

​ 服务容器化,横空出世;依赖注入,孕育而生

.NET 8 IApplicationBuilder详解的更多相关文章

  1. net core 中间件详解及项目实战

    net core 中间件详解及项目实战 前言 在上篇文章主要介绍了DotNetCore项目状况,本篇文章是我们在开发自己的项目中实际使用的,比较贴合实际应用,算是对中间件的一个深入使用了,不是简单的H ...

  2. 在ASP.NET 5应用程序中的跨域请求功能详解

    在ASP.NET 5应用程序中的跨域请求功能详解 浏览器安全阻止了一个网页中向另外一个域提交请求,这个限制叫做同域策咯(same-origin policy),这组织了一个恶意网站从另外一个网站读取敏 ...

  3. Middleware详解

    Middleware详解 在第1章项目结构分析中,我们提到Startup.cs作为整个程序的入口点,等同于传统的Global.asax文件,即:用于初始化系统级的信息(例如,MVC中的路由配置).本章 ...

  4. IdentityServer4实战 - JWT Token Issuer 详解

    原文:IdentityServer4实战 - JWT Token Issuer 详解 一.前言 本文为系列补坑之作,拖了许久决定先把坑填完. 下文演示所用代码采用的 IdentityServer4 版 ...

  5. 【半小时大话.net依赖注入】(下)详解AutoFac+实战Mvc、Api以及.NET Core的依赖注入

    系列目录 上|理论基础+实战控制台程序实现AutoFac注入 下|详解AutoFac+实战Mvc.Api以及.NET Core的依赖注入 前言 本来计划是五篇文章的,每章发个半小时随便翻翻就能懂,但是 ...

  6. [转帖]ASP.NET Core 中间件(Middleware)详解

    ASP.NET Core 中间件(Middleware)详解   本文为官方文档译文,官方文档现已非机器翻译 https://docs.microsoft.com/zh-cn/aspnet/core/ ...

  7. Asp.Net Core 中IdentityServer4 实战之角色授权详解

    一.前言 前几篇文章分享了IdentityServer4密码模式的基本授权及自定义授权等方式,最近由于改造一个网关服务,用到了IdentityServer4的授权,改造过程中发现比较适合基于Role角 ...

  8. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  9. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  10. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

随机推荐

  1. wordcloud 词云Python

    from wordcloud import WordCloud import matplotlib.pyplot as plt def get_word_cloud(words_list): #首先实 ...

  2. 剑指offer53(Java)-在排序数组中查找数字(简单)

    题目: 统计一个数字在排序数组中出现的次数. 示例 1: 输入: nums = [5,7,7,8,8,10], target = 8输出: 2示例 2: 输入: nums = [5,7,7,8,8,1 ...

  3. 力扣181(MySQL)- 超过经理收入的员工(简单)

    题目: 表:Employee 编写一个SQL查询来查找收入比经理高的员工. 以 任意顺序 返回结果表. 查询结果格式如下所示. 示例 1:  解题思路: 一.[子查询] 先通过子查询找到当前员工的经理 ...

  4. 力扣506(java)-相对名次(简单)

    题目: 给你一个长度为 n 的整数数组 score ,其中 score[i] 是第 i 位运动员在比赛中的得分.所有得分都互不相同 . 运动员将根据得分 决定名次 ,其中名次第 1 的运动员得分最高, ...

  5. C#的基于.net framework的Dll模块编程(二) - 编程手把手系列文章

    今天继续这个系列博文的编写.接上次的篇幅,这次介绍关于C#的Dll类库的创建的内容.因为是手把手系列,所以对于需要入门的朋友来说还是挺好的,下面开始咯: 一.新建Dll类库: 这里直接创建例子的Dll ...

  6. Fluid 0.5 版本发布:开启数据集缓存在线弹性扩缩容之路

    简介: 为了解决大数据.AI 等数据密集型应用在云原生场景下,面临的异构数据源访问复杂.存算分离 I/O 速度慢.场景感知弱调度低效等痛点问题,南京大学PASALab.阿里巴巴.Alluxio 在 2 ...

  7. [FAQ] Beego2.0.2 bee 生成的 api 项目运行 404, http server Running on http://:8080

    Beego, bee version 2.0.2 https://github.com/beego/beego/issues/4363 Tool:AI 编程助手 Refer:Beego还流行吗 Lin ...

  8. 2019-10-14-云之幻-UWP-视频教程

    title author date CreateTime categories 云之幻 UWP 视频教程 lindexi 2019-10-14 21:8:26 +0800 2019-10-14 21: ...

  9. 04.Java 流程控制

    1.用户交互 Scanner Scanner 对象:获取用户的输入 基本语法:Scanner s = new Scanner(System.in); 通过 Scanner 类的 next() 和 ne ...

  10. go-admin migrate 数据表迁移

    目录 视频教程 应用场景 目录说明 数据迁移 迁移步骤 配置数据库 常用命令示例 新建模型实例 3.1 方式一:不编译运行(推荐) 3.2 方式二:编译并运行迁移 3.3 方式三:golangIDE ...