11、WebHost  第六个对象

  到目前为止我们已经知道了由一个服务器和多个中间件构成的管道是如何完整针对请求的监听、接收、处理和最终响应的,接下来来讨论这样的管道是如何被构建出来的。管道是在作为应用宿主的WebHost对象启动的时候被构建出来的,在ASP.NET Core Mini中,我们将表示应用宿主的IWebHost接口简写成如下的形式:只包含一个StartAsync方法用来启动应用程序。

public interface IWebHost
{
Task StartAsync();
}

  由于由WebHost构建的管道由Server和HttpHandler构成,我们在默认实现的WebHost类型中,我们直接提供者两个对象。在实现的StartAsync方法中,我么只需要将后者作为参数调用前者的StartAsync方法将服务器启动就可以了。

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);
}

12、WebHostBuilder  第七个对象

  作为最后一个着重介绍的核心对象,WebHostBuilder的使命非常明确:就是创建作为应用宿主的WebHost。由于在创建WebHost的时候需要提供注册的服务器由所有注册中间件构建而成的RequestDelegate,所以在对应接口IWebHostBuilder中,我们为它定义了三个核心方法。

public interface IWebHostBuilder
{
IWebHostBuilder UseServer(IServer server);
IWebHostBuilder Configure(Action<IApplicationBuilder> configure);
IWebHost Build();
}

  除了用来创建WebHost的Build方法之外,我们提供了用来注册服务器的UseServer方法和用来注册中间件的Configure方法。Configure方法提供了一个类型为Action<IApplicationBuilder>的参数,意味着我们针对中间件的注册是利用上面介绍的IApplicationBuilder对象来完成的。

  如下所示的WebHostBuilder是针对IWebHostBuilder接口的默认实现,它具有两个字段分别用来保存注册的中间件和调用Configure方法提供的Action<IApplicationBuilder>对象。当Build方法被调用之后,我们创建一个ApplicationBuilder对象(方法内部使用new ApplicationBuilder并添加相关配置),并将它作为参数调用这些Action<IApplicationBuilder>委托,进而将所有中间件全部注册到这个ApplicationBuilder对象上。我们最终调用它的Build方法得到由所有中间件共同构建的RequestDelegate对象,并利用它和注册的服务器构建作为应用宿主的WebHost对象。

public class WebHostBuilder : IWebHostBuilder
{
private IServer _server;
private readonly List<Action<IApplicationBuilder>> _configures = new List<Action<IApplicationBuilder>>(); public IWebHostBuilder Configure(Action<IApplicationBuilder> 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());
}
}

13、回顾一下Hello World 2

  到目前为止,我们已经将ASP.NET Core Mini涉及的七个核心对象介绍完了,然后我们再来回顾一下建立在这个模拟框架上的Hello World程序。

public class Program
{
public static async Task Main()
{
await new WebHostBuilder()
.UseHttpListener()
.Configure(app => app
.Use(FooMiddleware)
.Use(BarMiddleware)
.Use(BazMiddleware))
.Build()
.StartAsync();
}
public static RequestDelegate FooMiddleware(RequestDelegate next)
=> async context => {
await context.Response.WriteAsync("Foo=>");
await next(context);
};
public static RequestDelegate BarMiddleware(RequestDelegate next)
=> async context => {
await context.Response.WriteAsync("Bar=>");
await next(context);
};
public static RequestDelegate BazMiddleware(RequestDelegate next)
=> context => context.Response.WriteAsync("Baz");
}

  首选我们调用WebHostBuilder的扩展方法UseHttpListener采用如下的方式完成了针对HttpListenerServer的注册。由于中间件体现为一个Func<RequestDelegate, RequestDelegate>对象,我们自然可以采用与之具有相同声明的方法(FooMiddleware、BarMiddleware和BazMiddleware)来定义对应的中间件。中间件调用HttpResponse的WriteAsync以如下的方式将指定的字符串写入响应主体的输出流。

public static partial class Extensions
{
public static IWebHostBuilder UseHttpListener(this IWebHostBuilder builder, params string[] urls)
=> builder.UseServer(new HttpListenerServer(urls)); public static Task WriteAsync(this HttpResponse response, string contents)
{
var buffer = Encoding.UTF8.GetBytes(contents);
return response.Body.WriteAsync(buffer, , buffer.Length);
}
}

  ASP.NET Core Mini模拟了真实ASP.NET Core框架最核心的部分,即由服务器和中间件构成的请求处理管道。真正的ASP.NET Core框架自然要复杂得多得多,那么我们究竟遗漏了什么呢?

  如上所示的5个部分是ASP.NET Core Mini没有涉及的,其中包括依赖注入、以Startup和StartupFilter的中间件注册方式、针对多种数据源的配置系统、诊断日志系统和一系列预定义的中间件,上述的每个方面都涉及到一个庞大的主题,我们将ASP.NET Core涉及到的方方面都写在我将要出版的《ASP.NET Core框架揭秘》中,如果你想全方面了解一个真实的ASP.NET Core框架,敬请期待新书出版。

ASP.NET Core框架深度学习(四)宿主对象的更多相关文章

  1. ASP.NET Core框架深度学习(一) Hello World

    对于学习Core的框架,对我帮助最大的一篇文章是Artech的<200行代码,7个对象——让你了解ASP.NET Core框架的本质>,最近我又重新阅读了一遍该文.本系列文章就是结合我的阅 ...

  2. ASP.NET Core框架深度学习(二) 管道对象

    4.HttpContext 第一个对象 我们的ASP.NET Core Mini由7个核心对象构建而成.第一个就是大家非常熟悉的HttpContext对象,它可以说是ASP.NET Core应用开发中 ...

  3. ASP.NET Core框架深度学习(三) Server对象

    8.Server   第五个对象 服务器在管道中的职责非常明确,当我们启动应用宿主的WebHost的时候,服务它被自动启动.启动后的服务器会绑定到指定的端口进行请求监听,一旦有请求抵达,服务器会根据该 ...

  4. ASP.NET Core 框架本质学习

    本文作为学习过程中的一个记录. 学习文章地址: https://www.cnblogs.com/artech/p/inside-asp-net-core-framework.html 一. ASP.N ...

  5. C#中的函数式编程:递归与纯函数(二) 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面

    C#中的函数式编程:递归与纯函数(二)   在序言中,我们提到函数式编程的两大特征:无副作用.函数是第一公民.现在,我们先来深入第一个特征:无副作用. 无副作用是通过引用透明(Referential ...

  6. 200行代码,7个对象——让你了解ASP.NET Core框架的本质

    2019年1月19日,微软技术(苏州)俱乐部成立,我受邀在成立大会上作了一个名为<ASP.NET Core框架揭秘>的分享.在此次分享中,我按照ASP.NET Core自身的运行原理和设计 ...

  7. 了解ASP.NET Core框架的本质

    了解ASP.NET Core框架的本质 ASP.NET Core自身的运行原理和设计思想创建了一个 “迷你版” 的ASP.NET Core框架,并且利用这个 “极简” 的模拟框架阐述了ASP.NET ...

  8. 200行代码,7个对象——让你了解ASP.NET Core框架的本质

    原文:200行代码,7个对象--让你了解ASP.NET Core框架的本质 2019年1月19日,微软技术(苏州)俱乐部成立,我受邀在成立大会上作了一个名为<ASP.NET Core框架揭秘&g ...

  9. ASP.NET Core框架的本质

    源文章地址:http://www.cnblogs.com/artech/p/inside-asp-net-core-framework.html 1.从Hello World谈起 当我们最开始学习一门 ...

随机推荐

  1. 母版页 treeview控件 SiteMapPath控件 treeview数据库绑定模式

     母版页就是网站中一样的部分母版页的后缀名是.Master可以把母版页当成一个页面  想让哪里是别的内容就可以  通过如下: <asp:ContentPlaceHolder ID="C ...

  2. 查看Linux服务器CPU总核数

    下面介绍查看Linux服务器CPU总核数的方法. 通过/proc/cpuinfo可查看CPU个数及总核数. [root@kevin ~]# grep processor /proc/cpuinfo | ...

  3. Spring Boot 2.2.2.RELEASE 版本中文参考文档

    写在前面 在我初次接触MongoDB的时候,是为了做一个监控系统和日志分析系统.当时在用Java操作MongoDB数据里的数据的时候,都是在网上查找Demo示例然后完成的功能,相信大家也同样的体会,网 ...

  4. python判断字符串中是否包含子字符串

    python判断字符串中是否包含子字符串 s = '1234问沃尔沃434' if s.find('沃尔沃') != -1:     print('存在') else:     print('不存在' ...

  5. .netcore2.1 JS-SDK 从后台获取微信签名,实现自定义分享标题、描述、图片

    最近项目移动端需要实现微信自定义分享功能,包含分享自定义标题.描述等. 首先到公众号的后台,功能设置里面,添加将要被分享的域名,如图 后端签名算法实现 ,参考腾讯开发者文档https://mp.wei ...

  6. js 报错 Uncaught TypeError: Cannot read property 'trim' of undefined

    jquery Uncaught TypeError: Cannot read property 'trim' of undefined 报错原因及解决方案 $.trim() 函数用于去除字符串两端的空 ...

  7. iOS多线程定时器

    在使用定时器时,我们经常使用NSTimer,但是由于NSTimer会受RunLoop影响,当RunLoop处理的任务很多时,就会导致NSTimer的精度降低,所以在一些对定时器精度要求很高的情况下,应 ...

  8. [20191112]oracle共享连接模式端口.txt

    [20191112]oracle共享连接模式端口.txt --//如果使用共享服务模式,你可以发现每次重启数据库对应的端口号会发生变化.# netstat -tunlp | egrep "A ...

  9. Python—实现钉钉后台开发

    二.实现钉钉免登流程 免登流程分四步:1.前端获取钉钉免登授权码code:2.后端获取access_token:3.使用授权码code和access_token换取用户userid:4.通过acces ...

  10. 7. java 数组概念

    一.数组概念 ​ 数组:是一种容器,可以同时存放多个数据值: ​ 特点:数组是一种引用类型:数组中多个数据,类型必须统一:数组的长度在程序运行期间不可改变: 二.数组初始化 1. 动态初始化(指定长度 ...