.NET 8 IEndpointRouteBuilder详解
Map
经过对 WebApplication 的初步剖析,我们已经大致对Web应用的骨架有了一定了解,现在我们来看一下Hello World案例中仅剩的一条代码:
app.MapGet("/", () => "Hello World!"); // 3 添加路由处理
老规矩,看签名:
public static RouteHandlerBuilder MapGet(this IEndpointRouteBuilder endpoints,
[StringSyntax("Route")] string pattern,Delegate handler){
return endpoints.MapMethods(pattern, (IEnumerable<string>) EndpointRouteBuilderExtensions.GetVerb, handler);
}
我们已经解释过 IEndpointRouteBuilder 的定义了,即为程序定义路由构建的约定。这次看到的是他的拓展方法 Map ,该方法是诸如 MapGet、MapPost、MapPut、MapDelete、MapPatch、MapMethods 的底层方法:

他的实现就是为了给IEndpointRouteBuilder 的 DataSources 添加一个 RouteEndpointDataSource
private static RouteHandlerBuilder Map(this IEndpointRouteBuilder endpoints, RoutePattern pattern, Delegate handler, IEnumerable<string> httpMethods, bool isFallback)
{
return endpoints.GetOrAddRouteEndpointDataSource().AddRouteHandler(pattern, handler, httpMethods, isFallback, RequestDelegateFactory.InferMetadata, RequestDelegateFactory.Create);
}
RouteEndpointDataSource 继承自 EndpointDataSource,提供一组RouteEndpoint
public override IReadOnlyList<RouteEndpoint> Endpoints
{
get
{
RouteEndpoint[] array = new RouteEndpoint[_routeEntries.Count];
for (int i = 0; i < _routeEntries.Count; i++)
{
array[i] = (RouteEndpoint)CreateRouteEndpointBuilder(_routeEntries[i]).Build();
}
return array;
}
}
Endpoint
RouteEndpoint 继承自 Endpoint。多了一个 RoutePattern 属性,用于路由匹配,支持模式路由。还有一个 Order 属性,用于处理多匹配源下的优先级问题。
public sealed class RouteEndpoint : Endpoint
{
public int Order { get; }
public RoutePattern RoutePattern { get; }
}
Endpoint 是一个应用程序中路的一个逻辑终结点。
public string? DisplayName { get; } // 终结点名称
public EndpointMetadataCollection Metadata { get; } // 元数据
public RequestDelegate? RequestDelegate { get; } // 请求委托
其中 Metadata 就是一个object集合,包含描述、标签、权限等数据,这一般是框架用到的,后面会再次见到它。重点是 RequestDelegate:HttpContext 首次登场,相信有过Web开发经验的同学熟悉的不能再熟悉。该委托其实就是一个Func<HttpContext, Task>,用于处理HTTP请求,由于TAP的普及,所以返回的Task。
public delegate Task RequestDelegate(HttpContext context);
Endpoint 一般由 EndpointBuilder 构建,他能够额外组装Filter
public IList<Func<EndpointFilterFactoryContext, EndpointFilterDelegate, EndpointFilterDelegate>> FilterFactories
EndpointDataSource
经过对 MapGet 的剖析我们最终发现,所有的终结点都被挂载在了 EndpointDataSource
public abstract IReadOnlyList<Endpoint> Endpoints { get; }
public virtual IReadOnlyList<Endpoint> GetGroupedEndpoints(RouteGroupContext context)
除了被大家熟悉的 Endpoints 还提供了一个方法 GetGroupedEndpoints:在给定指定前缀和约定的情况下,获取此EndpointDataSource 的所有 Endpoint的。
public virtual IReadOnlyList<Endpoint> GetGroupedEndpoints(RouteGroupContext context)
{
IReadOnlyList<Endpoint> endpoints = Endpoints;
RouteEndpoint[] array = new RouteEndpoint[endpoints.Count];
for (int i = 0; i < endpoints.Count; i++)
{
Endpoint endpoint = endpoints[i];
if (!(endpoint is RouteEndpoint routeEndpoint))
{
throw new NotSupportedException(Resources.FormatMapGroup_CustomEndpointUnsupported(endpoint.GetType()));
}
RoutePattern routePattern = RoutePatternFactory.Combine(context.Prefix, routeEndpoint.RoutePattern);
RouteEndpointBuilder routeEndpointBuilder = new RouteEndpointBuilder(routeEndpoint.RequestDelegate, routePattern, routeEndpoint.Order)
{
DisplayName = routeEndpoint.DisplayName,
ApplicationServices = context.ApplicationServices
};
foreach (Action<EndpointBuilder> convention in context.Conventions)
{
convention(routeEndpointBuilder);
}
foreach (object metadatum in routeEndpoint.Metadata)
{
routeEndpointBuilder.Metadata.Add(metadatum);
}
foreach (Action<EndpointBuilder> finallyConvention in context.FinallyConventions)
{
finallyConvention(routeEndpointBuilder);
}
array[i] = (RouteEndpoint)routeEndpointBuilder.Build();
}
return array;
}
通过剖析 RouteGroupContext,很容易发觉,Prefix 是一个路由前缀,Conventions 和 FinallyConventions 是两个约定hook。它专为 RouteEndpoint 独有,通过 GetGroupedEndpoints 方法,组的前缀和约定,会作用到每一个路由终结点。
public sealed class RouteGroupContext
{
public required RoutePattern Prefix { get; init; }
public IReadOnlyList<Action<EndpointBuilder>> Conventions { get; init; } = Array.Empty<Action<EndpointBuilder>>();
public IReadOnlyList<Action<EndpointBuilder>> FinallyConventions { get; init; } = Array.Empty<Action<EndpointBuilder>>();
}
.NET 8 IEndpointRouteBuilder详解的更多相关文章
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
- Git初探--笔记整理和Git命令详解
几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
- Node.js npm 详解
一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...
- .NET应用和AEAI CAS集成详解
1 概述 数通畅联某综合SOA集成项目的统一身份认证工作,需要第三方系统配合进行单点登录的配置改造,在项目中有需要进行单点登录配置的.NET应用系统,本文专门记录.NET应用和AEAI CAS的集成过 ...
随机推荐
- win10使用Docker Desktop启动mysql报错:Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:3306 -> 0.0.0.0:0: listen tcp 0.0.0.0:3306:
问题描述 今天上班用wind10电脑启动Docker Desktop使用MySQL,突然间报了一个错,错误如下: Error response from daemon: Ports are not a ...
- JVM虚拟机栈
JVM虚拟机栈 1.概述 1.1背景 由于跨平台性的设计,Java的指令都是根据栈来设计的.不同平台CPU架构不同,所以不能设计为基于寄存器的. 优点是跨平台,指令集小,编译器容易实现,缺点是性能下降 ...
- UE构建基础和实践:五、CI/CD平台自动化打包
序言 使用CI/CD平台构建(这里使用蓝盾平台)主要是通过平台脚本运行上一章的py脚本并传递参数(即把py中的参数开放给配置平台脚本配置). Build.py 重构 我们需要在py脚本里面解析和设置参 ...
- Linux学习环境搭建(VMware虚拟机安装Linux)
企业现状 目前绝大多数企业运维人员的工作环境都是Windows下通过SSH工具(如XShell等)远程连接千百里外的服务器进行管理和维护的. 而且学Linux运维,99.9%知识与硬件无关,用虚拟机足 ...
- 论文解读(MCADA)《Multicomponent Adversarial Domain Adaptation: A General Framework》
Note:[ wechat:Y466551 | 可加勿骚扰,付费咨询 ] 论文信息 论文标题:Multicomponent Adversarial Domain Adaptation: A Gener ...
- 为 VitePress 网站添加 RSS 订阅支持
省流:使用 vitepress-plugin-rss 这个插件 前言 在看许多个人博客站点的时候,右上角总会有个RSS订阅的标志 恰好我的博客也是基于 VitePress 搭建的,就想看看能不能也实现 ...
- 完美解决Content type ‘multipart/form-data;boundary=----------0467042;charset=UTF-8‘ not supported问题
一.前言 今天在做文件上传功能出现了该问题,该接口如下: @PostMapping("/upload") public Boolean upload(@RequestParam ...
- 代码随想录算法训练营第二十八天| 93.复原IP地址 78.子集 90.子集II
93.复原IP地址 卡哥建议:本期本来是很有难度的,不过 大家做完 分割回文串 之后,本题就容易很多了 题目链接/文章讲解:https://programmercarl.com/0093.%E5% ...
- Go开始:Go基本元素介绍
本文深入探讨了Go编程语言中的核心概念,包括标识符.关键字.具名函数.具名值.定义类型.类型别名.包和模块管理,以及代码块和断行.这些元素是构成Go程序的基础,也是编写高质量代码的关键. 关注Tech ...
- mysql8关闭binlog并清空Binlog
编辑my.ini或者my.cnf文件 清空binlog信息 #查看现存的binlog文件列表 show master logs; #重置清空binlog文件 reset master; #重置清空后 ...