首页 > 其他分享 >.NET 8 IEndpointRouteBuilder详解

.NET 8 IEndpointRouteBuilder详解

时间:2023-11-08 18:14:35浏览次数:45  
标签:IReadOnlyList get RouteEndpoint 详解 context NET endpoints public IEndpointRouteBu

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 ,该方法是诸如 MapGetMapPostMapPutMapDeleteMapPatchMapMethods 的底层方法:

​ 他的实现就是为了给IEndpointRouteBuilderDataSources 添加一个 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集合,包含描述、标签、权限等数据,这一般是框架用到的,后面会再次见到它。重点是 RequestDelegateHttpContext 首次登场,相信有过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 是一个路由前缀,ConventionsFinallyConventions 是两个约定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>>();
}

标签:IReadOnlyList,get,RouteEndpoint,详解,context,NET,endpoints,public,IEndpointRouteBu
From: https://www.cnblogs.com/xiaolipro/p/17818017.html

相关文章

  • org.apache.log4j.Logger 详解
    org.apache.log4j.Logger 详解1. 概述1.1. 背景  在应用程序中添加日志记录总的来说基于三个目的 :监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作;跟踪代码运行时轨迹,作为日后审计的依据;担当集成开发环境中的调试器的作用,向文件或控制台打......
  • 软件测试|MySQL BETWEEN AND:范围查询详解
    简介在MySQL数据库中,使用BETWEENAND操作符可以进行范围查询,即根据某个字段的值在指定范围内进行检索数据。这个操作符非常有用,因为它可以让我们轻松地筛选出位于两个特定值之间的数据,而不需要使用复杂的条件语句。BETWEENAND操作符的语法BETWEENAND操作符的基本语法如下:SE......
  • Redis配置文件详解
    Redis的配置文件redis.conf过滤掉空行和注释行,总共有49个可控项。1daemonizeno默认情况下,redis不是后台运行,如果需要后台运行,把该项的值改为yes。2pidfile当Redis在后台运行的时候,Redis默认会把pid文件放在/var/run/redis.pid,你可以配置到其他地址。当运行多个redis服务时,需......
  • geonetwork源码编译与开发入门说明
    本文介绍geonetwork源码编译及简单的开发修改。本文包括源码调试的细节,主要给没怎么接触过java又想调试修改部分java代码的提供一定帮助,比如控制器或修改业务逻辑中的增删改操作等本文使用环境:操作系统:Windows11JDK版本:jdk-8u381-windows-x64.exeMaven版本:apache-maven-3.9.......
  • 详解MySQL中EXPLAIN解释
    explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。使用方法,在select语句前加上explain就可以了:EXPLAIN列的解释:table:显示这一行的数据是关于哪张表的type:这是重要的列,显示连接使用了何种类......
  • 实例详解构建数仓中的行列转换
    本文分享自华为云社区《GaussDB数据库SQL系列-行列转换》,作者:Gauss松鼠会小助手2。一、前言在构建数据仓库或做数据分析时,需要对原始数据的结构进行一定的处理,有时涉及到“行转列”,有时涉及到“列转行”,那么这两个转换的方式具体是什么,有什么差异,怎么实现,今天我们将以GaussDB数......
  • 机器学习——深度卷积神经网络AlexNet
    AlexNet相对于LeNet的主要优势包括:1.更深的网络结构AlexNet有8层结构,而LeNet只有5层。网络更加深入有利于学习更抽象的高级特征。2.使用ReLU激活函数AlexNet使用ReLU激活函数,避免梯度消失问题,使得深层网络的训练更加容易。3.引入Dropout操作AlexNet在全连接层使用Dro......
  • 最全面的移动端UI组件设计详解:下篇
    上一期给大家讲解了《最全面的移动端UI组件设计详解:中篇》,主要分享了:基础组件、表单组件和反馈组件3个部分;这次给大家带来:数据展示组件和其他组件详解,希望你在设计APP、小程序、H5页面中,能熟练使用和理解各种的UI组件,今天给大家总结了关于移动端UI组件,希望可以在工作中帮到你。......
  • Spring 3.0 注解注入详解
    一、各种注解方式 1.@Autowired注解(不推荐使用,建议使用@Resource)     @Autowired可以对成员变量、方法和构造函数进行标注,来完成自动装配的工作。@Autowired的标注位置不同,它们都会在Spring在初始化这个bean时,自动装配这个属性。要使@Autowired能够工作,还需要在配置文件中......
  • PostgreSQL CPU占用高分析,查询IO消耗最高的SQL,查询耗时最长的SQL,查询被锁住的session
    查看当前活跃的DB session 正在运行的SQL语句(运行时间超过10秒)SELECTnow()-query_startas"runtime",usename,application_name,client_hostname,datname,state,query FROMpg_stat_activity WHEREnow()-query_start>'10seconds'::interval ......