.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的集成过 ...
随机推荐
- go build怎么使用
go build 是 Go 语言编译器的一个命令,用于将 Go 源代码文件编译成可执行的二进制文件.它是 Go 语言开发过程中常用的一个命令.以下是 go build 的基本使用方法: go buil ...
- React: Warning: `value` prop on `input` should not be null.
警告 解决方案 对value进行判断 修改后的效果 至此问题解决
- Abstract Factory 抽象工厂模式简介与 C# 示例【创建型1】【设计模式来了_1】
〇.简介 1.什么是抽象工厂模式? 一句话解释: 提供一个接口,以创建一系列相关或相互依赖的抽象对象,而无需指定它们具体的类.(将一系列抽象类装进接口,一次接口实现,就必须实例化这一系列抽象类) ...
- 使用 FastGPT 构建高质量 AI 知识库
作者:余金隆.FastGPT 项目作者,Sealos 项目前端负责人,前 Shopee 前端开发工程师 FastGPT 项目地址:https://github.com/labring/FastGPT/ ...
- DDD项目落地之充血模型实践
背景: 充血模型是DDD分层架构中实体设计的一种方案,可以使关注点聚焦于业务实现,可有效提升开发效率.提升可维护性: 1.DDD项目落地整体调用关系 调用关系图中的Entity为实体,从进入领域服务( ...
- 三维模型OSGB格式轻量化重难点分析
三维模型OSGB格式轻量化重难点分析 在三维模型应用中,为了适应移动设备的硬件和网络限制等问题,OSGB格式轻量化处理已经成为一个重要的技术手段.但是,在实际应用中,OSGB格式轻量化仍然存在着一些重 ...
- Docker部署cas
一.首先安装cas镜像 1.拉取cas docker镜像 docker pull apereo/cas 2.启动容器: docker run --name cas -p 8443:8443 -p 8 ...
- vscod 配置 morkdown 快捷键
vscod 配置 morkdown 快捷键 1.首先在根目录添加.vscode 文件夹 ️1.1 新建一个 settings.json 文件 { "[markdown]": { & ...
- Web攻防--JNDI注入--Log4j漏洞--Fastjson反序列化漏洞
JNDI注入 什么是JNDI JNDI全称为 Java Naming and Directory Interface(Java命名和目录接口),是一组应用程序接口,为开发人员查找和访问各种资源提供了统 ...
- 面试官:说一下 MyBatis 缓存机制?
MyBatis 的缓存机制属于本地缓存,适用于单机系统,它的作用是减少数据库的查询次数,提高系统性能. MyBaits 中包含两级本地缓存: 一级缓存:SqlSession 级别的,是 MyBatis ...