14

写一个简版 asp.net core

 3 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzAxMjE2NTMxMw%3D%3D&%3Bmid=2456606176&%3Bidx=1&%3Bsn=89beddf015e2eaa79db23cb72d98d7a6
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

动手写一个简版 asp.net core

Intro

之前看到过蒋金楠老师的一篇 200 行代码带你了解 asp.net core 框架,最近参考蒋老师和 Edison 的文章和代码,结合自己对 asp.net core 的理解 ,最近自己写了一个 MiniAspNetCore ,写篇文章总结一下。

HttpContext

HttpContext 可能是最为常用的一个类了,  HttpContext 是请求上下文,包含了所有的请求信息以及响应信息,以及一些自定义的用于在不同中间件中传输数据的信息

来看一下 HttpContext 的定义:

HttpRequest 即为请求信息对象,包含了所有请求相关的信息,

HttpResponse 为响应信息对象,包含了请求对应的响应信息

RequestServices 为 asp.net core 里的  RequestServices ,代表当前请求的服务提供者,可以使用它来获取具体的服务实例

Features 为 asp.net core 里引入的对象,可以用来在不同中间件中传递信息和用来解耦合

,下面我们就来看下 HttpRequest 和  HttpResponse 是怎么实现的

HttpRequest:

HttpResponse:

Features

上面我们提供我们可以使用 Features 在不同中间件中传递信息和解耦合

由上面 HttpRequestHttpResponse 的代码我们可以看出来,  HttpRequest 和  HttpResponse 其实就是在  IRequestFeature 和  IResponseFeature 的基础上封装了一层,真正的核心其实是  IRequestFeatureIResponseFeature ,而这里使用接口就很好的实现了解耦,可以根据不同的 WebServer 使用不同的  RequestFeatureResponseFeature ,来看下  IRequestFeatureIResponseFeature 的实现

这里的实现和 asp.net core 的实际的实现方式应该不同,asp.net core 里 Headers 同一个 Header 允许有多个值,asp.net core 里是 StringValues 来实现的,这里简单处理了,使用了一个 NameValueCollection 对象

上面提到的 Features 是一个  IFeatureCollection 对象,相当于是一系列的  Feature 对象组成的,来看下  FeatureCollection 的定义:

这里 IFeatureCollection 直接实现  IDictionary<Type,object> ,通过一个字典 Feature 类型为 Key,Feature 对象为 Value 的字典来保存

为了方便使用,可以定义两个扩展方法来方便的Get/Set

Web服务器

uE3iUz6.jpg!web

上面我们已经提到了 Web 服务器通过 IRequestFeatureIResponseFeature 来实现不同 web 服务器和应用程序的解耦,web 服务器只需要提供自己的  RequestFeatureResponseFeature 即可

为了抽象不同的 Web 服务器,我们需要定义一个 IServer 的抽象接口,定义如下:

IServer 定义了一个  StartAsync 方法,用来启动 Web服务器,

StartAsync 方法有两个参数,一个是 requestHandler,是一个用来处理请求的委托,另一个是取消令牌用来停止 web 服务器

示例使用了 HttpListener 来实现了一个简单 Web 服务器,  HttpListenerServer 定义如下:

HttpListenerServer 实现的  RequestFeatureResponseFeatue

为了方便使用,为 HttpListenerContext 定义了两个扩展方法,就是上面  HttpListenerServer 中的  GetRequestFeatureGetResponseFeature

RequestDelegate

在上面的 IServer 定义里有一个 requestHandler 的 对象,在 asp.net core 里是一个名称为  RequestDelegate 的对象,而用来构建这个委托的在 asp.net core 里是  IApplicationBuilder ,这些在蒋老师和 Edison 的文章和代码里都可以看到,这里我们只是简单介绍下,我在 MiniAspNetCore 的示例中没有使用这些对象,而是使用了自己抽象的  PipelineBuilder 和原始委托实现的

asp.net core 里 RequestDelegate 定义:

其实和我们上面定义用的 Func<HttpContext,Task> 是等价的

IApplicationBuilder 定义:

我们这里没有定义 IApplicationBuilder ,使用了简化抽象的  IAsyncPipelineBuilder ,定义如下:

对于 asp.net core 的中间件来说 ,上面的 TContext 就是  HttpContext ,替换之后也就是下面这样的:

是不是和 IApplicationBuilder 很像,如果不像可以进一步把  Func<HttpContext,Task> 使用  RequestDelegate 替换

最后再将接口名称替换一下:

至此,就完全可以看出来了,这 IAsyncPipelineBuilder<HttpContext> 就是一个简版的  IApplicationBuilder

IAsyncPipelineBuilder 和  IApplicationBuilder 的作用是将注册的多个中间件构建成一个请求处理的委托

M7vqmqZ.png!web

中间件处理流程:

zIrqqiY.png!web

更多关于 PipelineBuilder 构建中间件的信息可以查看 让 .NET 轻松构建中间件模式代码 了解更多

WebHost

通过除了 Web 服务器之外,还有一个 Web Host 的概念,可以简单的这样理解,一个 Web 服务器上可以有多个 Web Host,就像 IIS/nginx (Web Server) 可以 host 多个站点

可以说 WebHost 离我们的应用更近,所以我们还需要 IHost 来托管应用

WebHost 定义:

为了方便的构建 Host 对象,引入了  HostBuilder 来方便的构建一个  Host ,定义如下:

WebHostBuilder

这里的示例我在 IHostBuilder 里增加了一个  Initialize 的方法来做一些初始化的操作,我觉得有些数据初始化配置初始化等操作应该在这里操作,而不应该在  Startup 的  Configure 方法里处理,这样  Configure 方法可以更纯粹一些,只配置 asp.net core 的请求管道,这纯属个人意见,没有对错之分

这里 Host 的实现和 asp.net core 的实现不同,有需要的可以深究源码,在 asp.net core 2.x 的版本里是有一个 IWebHost 的,在 asp.net core 3.x 以及 .net 5 里是没有  IWebHost 的取而代之的是通用主机  IHost , 通过实现了一个  IHostedService 来实现  WebHost

Run

运行示例代码:

在示例项目目录下执行 dotnet run ,并访问  http://localhost:5100/ :

miUfMbV.png!web

仔细观察浏览器 console 或  network 的话,会发现还有一个请求,浏览器会默认请求  /favicon.ico 获取网站的图标

因为我们针对这个请求没有任何中间件的处理,所以直接返回了 404

在访问 /test ,可以看到和刚才的输出完全不同,因为这个请求走了另外一个分支,相当于 asp.net core 里  MapMapWhen 的效果,另外  Run 代表里中间件的中断,不会执行后续的中间件

3iqEF3n.png!web

More

上面的实现只是我在尝试写一个简版的 asp.net core 框架时的实现,和 asp.net core 的实现并不完全一样,如果需要请参考源码,上面的实现仅供参考,上面实现的源码可以在 Github 上获取 https://github.com/WeihanLi/SamplesInPractice/tree/master/MiniAspNetCore

asp.net core 源码:https://github.com/dotnet/aspnetcore

Reference


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK