网站优秀网站地址专业团队英文
web/
2025/10/7 12:18:45/
文章来源:
网站优秀网站地址,专业团队英文,wordpress主题怎么汉化,php在网站开发中的作用老A说的一句话让我很受启发#xff0c;想要深入了解框架#xff0c;你要把精力聚焦在架构设计的层面来思考问题。而透彻了解底层原理#xff0c;最好的笨办法就是根据原理对框架核心进行重建或者说再造。看起来没有捷径#xff0c;也是最快的捷径。相信很多读者已经看过老A… 老A说的一句话让我很受启发想要深入了解框架你要把精力聚焦在架构设计的层面来思考问题。而透彻了解底层原理最好的笨办法就是根据原理对框架核心进行重建或者说再造。看起来没有捷径也是最快的捷径。 相信很多读者已经看过老A写的这篇文章《200行代码7个对象——让你了解ASP.NET Core框架的本质》这是一篇模仿和重建的典范。重建说白了就是模仿模仿有一个前置条件就是你对底层原理要烂熟于心。否则画虎难画骨原本要画虎最后出来的是只猫。要理解原理就要去阅读源码就像新人学开车如何使用尚且磕磕碰碰更何况让你去了解汽车的构造和引擎。 所以老A是引路人我像个门外汉一样对前辈的文章解读不下5遍。我有几个疑问1.为什么是7个对象2.这些对象如何分类如何排序3.这些对象发明的那个“无”是什么 在我深入学习和解读的时候我越加感觉到老A的这篇文章很值得去深入解读所谓知其然知其所以然这样在编码过程才会游刃有余以下开始我个人的解读。委托构建模式适配器模式public class Program{ public static void Main() new WebHostBuilder() .UseKestrel() .Configure(app app.Use(context context.Response.WriteAsync(Hello World!))) .Build() .Run();} 以上是原文的代码我们可以看到WebHostBuilder、Server即Kestrel、ApplicationBuilder(即app)三大重要的对象如下图所示 WebHostBuilder这个父亲生出WebHost这个孩子WebHost又生成整个ASP.NET Core最核心的内容即由Server和中间件(Middleware)构成的管道Pipeline。我们看下Pipeline的放大图 继续把Pipeline拆开有个很重要的ApplicationBuilder对象里面包含Middleware、RequestDelegate。至于HttpContext是独立共享的对象贯穿在整个管道中间至此7大对象全部出场完毕。Configure是个什么玩意看下代码public IWebHostBuilder Configure(ActionIApplicationBuilder configure){ _configures.Add(configure); return this;} 我们看到他是一个接受IApplicationBuilder的委托继续刨根问底IApplicationBuilder是什么玩意看下源码public interface IApplicationBuilder{ IApplicationBuilder Use(FuncRequestDelegate, RequestDelegate middleware); RequestDelegate Build();} 他是一个注册中间件和生成Application的容器那么Application是什么呢源码没有这个对象但是看代码如下所示我们可以知道他是真正的委托执行者Handler执行是一个动作可以理解为app我猜想这是取名为ApplicationBuilder的原因。public RequestDelegate Build(){ _middlewares.Reverse(); return httpContext { RequestDelegate next _ { _.Response.StatusCode 404; return Task.CompletedTask; }; foreach (var middleware in _middlewares) { next middleware(next); } return next(httpContext); };} 更详细的过程可以参考下面这张图(图片来源) WebHostBuilder开始Build的那一刻开始WebHost被构造Server被指定Middlewares被指定等WebHost真正启动的时候Server开始监听收到请求后Middleware开始执行。到此一个完整的ASP.NET Core的流程就简单的走完了。接下来我们跟着老A一个一个对象的详细介绍。1.HttpContext这个对象应该是最容易理解的也是我们在编程时候遇到的最多的最重要的没有之一对象。请看这个对象的简要代码public class HttpContext{ public HttpRequest Request { get; } public HttpResponse Response { get; }}public class HttpRequest{ public Uri Url { get; } public NameValueCollection Headers { get; } public Stream Body { get; }}public class HttpResponse{ public NameValueCollection Headers { get; } public Stream Body { get; } public int StatusCode { get; set;}} 我们知道一个Http事务包括最核心的Request输入和Response输出所以HttpContext包含这两个核心的东西。 老A建议大家从管道的角度来理解该对象的作用管道和HTTP请求流程一脉相承。在Server接收到请求后HttpContext被创建。 在服务器和中间件中间件之间通过什么来传递信息就是共享上下文这个上下文就是HttpContext。可以说HttpContext是根据HTTP请求原理包裹的在管道之间的共享的一个上下文对象。 为什么这里要把HttpContext放在第一个来介绍因为这是一个最基础的对象。这7大对象的讲解顺序我感觉是从底层基础开始讲起再层层往上最后到WebHostBuilder。2.RequestDelegate 这个委托太重要了和HttpContext一样老A建议大家从管道的角度来理解这个委托。我们再复习一下管道的含义如图所示 这里的管道Pipeline Server Middlewares 还能更简单一点吗可以的如下图所示 这里的管道Pipeline Server HttpHandler。 多个Middlewares构成一个HttpHandler对象这是整个管道的核心那么应该如何用代码来表示呢 老A讲到“既然针对当前请求的所有输入和输出都通过HttpContext来表示那么HttpHandler就可以表示成一个ActionHttpContext对象”。 但是由于ASP.NET Core推崇异步编程所以你应该想得到Task对象那么HttpHandler自然就可以表示为一个FuncHttpContextTask对象。由于这个委托对象实在太重要了所以我们将它定义成一个独立的类型。下图展示的就是整个RequestDelegate的设计思路1public delegate Task RequestDelegate(HttpContext context); 这就是委托的由来为什么是委托而不是别的函数 委托是架构设计的底层技术非常常见。因为委托可以承载约定的函数遵循开闭原则能很好的把扩展对外进行开放保证了底层架构的稳定性。3.Middleware 这个对象比较费解。根据源码我们知道Middleware也是一个委托对象代码如下所示中间件其实就是一个FuncRequestDelegate, RequestDelegate对象1private readonly ListFuncRequestDelegate, RequestDelegate _middlewares new ListFuncRequestDelegate, RequestDelegate(); 该对象的输入和输入都是RequestDelegate为什么要这么设计呢我们想一下当前中间件处理完成后需要将请求分发给后续中间件进行处理他如何让后续的中间件参与当前的请求呢所以他必须要拿到代表后续中间件管道构成的那个Handler。如下图所示也就是说后续三个中间件构成的管道就是一个输入执行完毕后当前中间件也将被“融入”这个管道此时该新管道就会由四个中间件构成的一个委托链然后再输出给你由所有的中间件构成的新管道。如下图所示4.ApplicationBuilder 这又是一个builder可见builder模式在ASP.NET Core有非常广泛的应用。但是该Builder构建的不是Application到构建什么内容呢从下面代码声明我们可以看到他有两个功能。 从Use的使用来看第一个功能是注册器他把一个个中间件串联成一个管道。public interface IApplicationBuilder{ IApplicationBuilder Use(FuncRequestDelegate, RequestDelegate middleware); RequestDelegate Build();} 第二个功能是Build如下所示public class ApplicationBuilder : IApplicationBuilder{ private readonly ListFuncRequestDelegate, RequestDelegate _middlewares new ListFuncRequestDelegate, RequestDelegate(); public RequestDelegate Build() { _middlewares.Reverse(); return httpContext { RequestDelegate next _ { _.Response.StatusCode 404; return Task.CompletedTask; }; foreach (var middleware in _middlewares) { next middleware(next); } return next(httpContext); }; } public IApplicationBuilder Use(FuncRequestDelegate, RequestDelegate middleware) { _middlewares.Add(middleware); return this; }} Build真正做的事情是循环组装中间件最后把组装好的委托链进行返回。从_middlewares.Reverse();我们又可以知道对于委托链来说中间件的注册顺序和执行顺序是相反的这里需要进行反转然后才能保证先注册的中间件先执行。5.ServerServer对象相对比较简单我们看下他的接口定义public interface IServer{ Task StartAsync(RequestDelegate handler);} 我们可以看到Server有个启动函数StartAsyncStartAsync内部封装了RequestDelegate中间件同时内部也会new一个HttpContext(features)这样Server、RequestDelegate、HttpContext三者就全部聚齐了。public class HttpListenerServer : IServer{ private readonly HttpListener _httpListener; private readonly string[] _urls; public HttpListenerServer(params string[] urls) { _httpListener new HttpListener(); _urls urls.Any()?urls: new string[] { http://localhost:5000/}; } public async Task StartAsync(RequestDelegate handler) { Array.ForEach(_urls, url _httpListener.Prefixes.Add(url)); _httpListener.Start(); Console.WriteLine(Server started and is listening on: {0}, string.Join(;, _urls)); while (true) { var listenerContext await _httpListener.GetContextAsync(); Console.WriteLine({0} {1} HTTP/{2}, listenerContext.Request.HttpMethod, listenerContext.Request.RawUrl, listenerContext.Request.ProtocolVersion); var feature new HttpListenerFeature(listenerContext); var features new FeatureCollection() .SetIHttpRequestFeature(feature) .SetIHttpResponseFeature(feature); var httpContext new HttpContext(features); Console.WriteLine([Info]: Server process one HTTP request start.); await handler(httpContext); Console.WriteLine([Info]: Server process one HTTP request end.); listenerContext.Response.Close(); } }}public static partial class Extensions{ public static IWebHostBuilder UseHttpListener(this IWebHostBuilder builder, params string[] urls) builder.UseServer(new HttpListenerServer(urls)); 通过以上代码分析我们可以画个图做总结适配器模式由于ASP.NET Core可以支持不同的WebServer比如Kestrel和IIS不同的WebServer返回的HttpContext各不相同所以这里又增加了一个中间层进行适配。这个中间层是什么呢如下图所示就是IRequestFeature和IResponseFeature。这一层是典型的适配器模式。 这里重点讲解的7大对象这个适配器模式的实现细节暂且略过。 6.WebHostpublic interface IWebHost{ Task StartAsync();} 根据这段定义我们只能知道简单知道WebHost只要是用来启动什么对象用的具体什么对象似乎都可以。直到我们看了实现如下代码所示public class WebHost : IWebHost{ private readonly IServer _server; private readonly RequestDelegate _handler; public WebHost(IServer server, RequestDelegate handler) { _server server; _handler handler; } public Task StartAsync() _server.StartAsync(_handler);} 通过StartAsync我们知道WebHost是用来启动管道的中间件的管道是在作为应用宿主的WebHost对象启动的时候被构建出来的。 而WebHost是如何被创建的呢接下来就要讲他的父亲WebHostBuilder7.WebHostBuilderpublic class WebHostBuilder : IWebHostBuilder{ private IServer _server; private readonly ListActionIApplicationBuilder _configures new ListActionIApplicationBuilder(); public IWebHostBuilder Configure(ActionIApplicationBuilder configure) { _configures.Add(configure); return this; } public IWebHostBuilder UseServer(IServer server) { _server server; return this; } public IWebHost Build() { var builder new ApplicationBuilder(); foreach (var configure in _configures) { configure(builder); } return new WebHost(_server, builder.Build()); }} 我们看到该对象有个Build方法内部返回一个WebHost对象这就是父亲的职责负责生娃他的娃就是WebHost。生出来的时候给孩子一个ApplicationBuilder作为食物。而这个食物其实是包裹起来的展开来看就是一个个RequestDelegate委托链。public interface IWebHostBuilder{ IWebHostBuilder UseServer(IServer server); IWebHostBuilder Configure(ActionIApplicationBuilder configure); IWebHost Build();} 父亲除了创建WebHost之外他还提供了注册服务器的UseServer方法和用来注册中间件的Configure方法。说到Configure方法我们一定还记得ApplicationBuilder方法的Use也是一个注册器。这两个注册器有何不同呢我们对比一下代码WebHostBuilderpublic IWebHostBuilder Configure(ActionIApplicationBuilder configure){ _configures.Add(configure); return this;}ApplicationBuilderpublic IApplicationBuilder Use(FuncRequestDelegate, RequestDelegate middleware){ _middlewares.Add(middleware); return this;} 其中Use只是增加一个中间件Configure输入的是中间件构成的委托链。我们看下入口函数的代码就知道了public static async Task Main(){ await new WebHostBuilder() .UseHttpListener() .Configure(app app .Use(FooMiddleware) .Use(BarMiddleware) .Use(BazMiddleware)) .Build() .StartAsync();}参加文章深入研究 Mini ASP.NET Core一个Mini的ASP.NET Core框架的实现200行代码7个对象——让你了解ASP.NET Core框架的本质原文地址https://www.cnblogs.com/jackyfei/p/10838586.html.NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/88469.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!