.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的集成过 ...
随机推荐
- Asp.Net MVC中Action跳转小结(转载)
来源: https://www.cnblogs.com/surfing/p/3542826.html 首先我觉得action的跳转大致可以这样归一下类,跳转到同一控制器内的action和不同控制器内的 ...
- 从0开发属于自己的nestjs框架的mini 版 —— ioc篇
如今,nodejs的框架也是层出不穷,偏向向底层的有 express.koa. Fastify,偏向于上层有阿里的 Egg.thinkjs .还有国外的 nestjs. 在这里我更喜欢 nestjs, ...
- Pandas:获取Dataframe索引
解决方案 效果图 参考链接 https://blog.csdn.net/YENTERTAINR/article/details/109254583
- 关于reids免安装的使用与注意事项
redis是我们现在常用的缓存数据库.可是redis官方网站只提供linux版本,而我们又习惯在windows系统上使用开发工具,这又怎么办呢? 幸好微软官方也提供了windows版本,方便根据实际需 ...
- LaZagne:一键抓取目标机器上的所有明文密码的神器
LaZagne 介绍 功能 LaZagne 是用于获取存储在本地计算机上的大量密码的开源应用程序. 每个软件都使用不同的技术(纯文本.API.自定义算法.数据库等)存储其密码.LaZagne 的作用就 ...
- spring-mvc系列:详解@RequestMapping注解(value、method、params、header等)
目录 一.@RequestMapping注解的功能 二.@RequestMapping注解的位置 三.@RequestMapping注解的value属性 四.@RequestMapping注解的met ...
- docker 安装 Influxdb-relay 使用
转载请注明出处: 1.influxdb relay的作用和特性 数据转发:InfluxDB Relay 可以从一个或多个源(input)接收数据,并将其转发到一个或多个目标(output)的 Infl ...
- 产品代码都给你看了,可别再说不会DDD(四):代码工程结构
这是一个讲解DDD落地的文章系列,作者是<实现领域驱动设计>的译者滕云.本文章系列以一个真实的并已成功上线的软件项目--码如云(https://www.mryqr.com)为例,系统性地讲 ...
- 一文解锁vue3中hooks的使用姿势
vue3 中的 hooks 是什么? 简单来说如果你的函数中用到了诸如 ref,reactive,onMounted 等 vue 提供的 api 的话,那么它就是一个 hooks 函数,如果没用到它就 ...
- LeetCode 周赛上分之旅 #44 同余前缀和问题与经典倍增 LCA 算法
️ 本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问. 学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越 ...