一、前言

只是讲asp.net core 3.x通用主机的大致原理,这些东西是通过查看源码以及自己根据经验总结得来的,在文章中不会深入源码,因为个人觉得懂原理就晓得扩展点,后期碰到有需求的时候再仔细去研究源码也不迟。
阅读前你应该先去了解下(推荐博客园老A的博客):

  • asp.net core中的依赖注入、
  • 配置,

讲解的方式是:

  1. 概述
  2. 逐一介绍核心类及扩展方式
  3. 通常我们如何使用
  4. 总结

二、概述

以前的控制台应用程序、winform程序启动时main首先被执行,后续都是我们自己的代码来实现框架和业务上的东东,比如我们要使用配置就ConfigurationManager.AppSettings... 若想使用依赖注入则需要引入第三方框架,比如autofact。asp.net framework时代也类似

在.net core 3.0之前的版本默认使用的是IWebHost,它内部定义了IOC容器(服务注册体现在Startup.ConfigServices),和各种配置源的设置(体现在Program配置主机时),我们后续的Controler、View、包括业务代码可以很容易做依赖注入和获取配置信息(包括运用选项模式)

有时候我们希望写一个服务,但是这个服务并不是用来做api/web,处理http请求的,比如想做一个物联网的后端采集服务,一直等待远端硬件设备提交实时数据过来,后端进行处理。但是又希望使用asp.net core提供的 配置、依赖注入、日志 和其它功能。后来微软就将asp.net core中的这套东西抽离出来了,叫做通用主机,用来承载任何服务,这些自定义服务中就可以很方便地使用配置、依赖注入、日志、和其它功能。现在asp.net core只是由通用主机承载的其中一种服务。

2.1、默认情况下主要的实现思路是:

2.1.1、定义(微软定义好的):

  • 定义HOST,它包含IOC根容器、主机和应用程序的生命周期事件定定义、IHostedService集合(一个实例就是一个服务或者叫应用,asp.net core就是一个这样的实例)
  • 允许调用方提供一堆委托来向IOC中注册服务、和设置主机和应用的“配置源”
  • 提供向主机添加IHostedService的实现对象的方法
  • 允许调用方注册主机和应用在启动和停止阶段触发的相应事件

2.1.2、配置(我们的代码,微软定义很多辅助方法):

  • 创建IHost实例
  • 向Host的IOC容器中注册各种服务
  • 配置主机和应用程序的“配置源
  • 向主机内部添加IHostedService实例(也就是我们最终的服务)
  • 主机和应用的生命周期事件,来实现一些特殊任务

2.1.3、启动阶段(微软定义好的)

  • 上面所谓的配置基本都是通过委托实现的(通常微软提供的各种扩展方法最终也是执行委托),回调这些委托以设置“配置源”和注册服务
  • 最后遍历启动HostedService
  • 在启动过程中还会回调相应的生命周期事件

2.2、啥是应用?

上面提了几次“应用”,现在对于主机来说asp.net core框架就是一个应用、我们上面举例说的"物联网后端服务"是另一个应用。从代码上来说就是一个IHostedService的实现。
主机和应用是一对多的关系,多个应用可以共享主机的信息,如:主机的IOC容器、主机的配置。应用配置。应用当然也可以自己去创建自己的IOC根容器和配置对象

主机配置和应用配置有关系?这两个配置对象都存在于Host中,主机配置是只跟主机相关的配置,应用配置是主机中多个应用共享的配置,如果主机中只有一个应用,那么完全可以拿它做最终的应用配置。另外应用配置包含主机配置

注意:在理解时要记住我们现在的目的是讲解通用主机,意思是可以承载你自己定义的服务的主机,别去想什么mvc controller action 路由之类的

三、核心类

下面分别介绍下主机中的几个核心默认实现类,几乎每个类都有对应的接口,为了缩短篇幅、便于理解就不讲接口了。

3.1、Host

它代表主机,用来宿主(承载)我们应用(一个IHostedService的实现)。
主要包含:日志、主机和应用的生命周期事件、IOC根容器、主机的选项对象、启动停止/停止方法。
接口中只定义了:IOC根容器 + Start + Stop方法
它在Program.Main中被创建、配置和启动

默认实现Microsoft.Extensions.Hosting.Internal.Host,它是一个internal的类,这个主机将来被启动时:

  • 触发主机的WaitForStartAsync事件
  • 逐一启动主机累不的hostedService
  • 触发_applicationLifetime?.NotifyStarted();事件
  • 停止时就反过来,先逐一停止hostedService,触发响应事件、最后停止主机

扩展:

因为默认Host是internal修饰的,所以无法继承

  • 自定义实现IHost;(这不说了,你可以随心所欲)
  • 订阅主机和应用的生命周期事件(实现IHostLifetime、IHostApplicationLifetime并添加到IOC容器)

大部分情况下方式2实现起来更容易也更常见

提一嘴,asp.net core 3.x现在也是使用的这个默认主机,只是在上面做了根web相关的配置,将在下一篇讲解

3.2、HostBuilder

Host的职责只是完成主机该有的功能,那么它的创建及配置最好另外定义一个类HostBuilder,它是Host的创建器(工厂),我们通常

  • 在系统启动时(Program.Man)先创建HostBuilder,
  • 然后进行配置(向IOC容器注册服务,设置主机和应用的"配置源"),
  • 最后调用Build方法生成我们最终的Host

通过接口IHostBuilder源码可以初略看出它(通过委托的方式)提供以下功能

  • 设置主机和应用的“配置源”
  • 配置IOC容器本身
  • 想IOC容器添加服务
  • 根据以后配置创建Host
  • 有个Properties属性,是个字典类型,可以在构建Host的多个步骤中传递数据

扩展:

对于我们使用者来说主要是通过它的方法向内部塞入各种委托,以达到向IOC容器注册服务和设置主机和应用的“配置源”
也可以但估计很少去实现主机的IHostBuilder;继承HostBuilder意义也不大,因为它没有提供抽象和虚方法

默认Build流程
初始化主机配置对象IConfiguration,主要是回调,主机没有做其它的
初始化主机环境对象_hostingEnvironment

  • 应用程序名字从上一步的主机配置里来
  • 环境名(开发?调试?)从配置里来,若没有则默认是生产模式"Production"
  • 内容根也从配置里来,若没有则是当前程序路径
  • 根据内容跟创建一个ContentRootFileProvider 实现类是PhysicalFileProvider

初始化HostBuilderContext,根据上面的配置和环境创建这个上下文(这里只是暂时用的主机配置,下面会被替换成应用的配置)
初始化应用配置

  • 以上面的内容根作为配置查找的根(若将来提供物理文件作为配置源时需要此属性)
  • 将主机配置塞入这个应用配置,所以应用配置=主机配置+回调后的配置
  • 最后将HostBuilderContext的Configuration替换为此配置对象

创建IOC容器

  • 创建ServiceCollection,并将上面的几个对象以单利模式放入进去
  • 还要放入IHostApplicationLifetime和IHostLifetime和Host
  • 开启选项模式,注册日志
  • 回调configureServicesAction
  • 调用工厂_serviceProviderFactory创建ServiceProvider
  • 回调_configureContainerActions
  • 最后返回容器

调用容器解析并返回Host

3.3、HostBuilder的工厂方法Host.CreateDefaultBuilder

上面有了Host,也有了对应的创建器HostBuilder,为啥还要再提供一个工厂方法呢?
因为职责分离原则,Host只负责承载应用并提供容器和设置配置源;HostBuilder只是负责配置并创建Host,尽可能提供一些默认值(前提时将来调用方未提供那些参数)。此时我们可以直接用HostBuilder来创建Host并启动它,但别忘了.net core是一个通用框架,它应提供一个更简洁的方式来创建最终的Host,因此它提供了静态方法Host.CreateDefaultBuilder,它尽可能提供更多的默认值,核心任务如下:

  • new HostBuilder
  • 设置程序的当前目录为内容根
  • 为主机配置 设置 环境变量作为配置源(只关注前缀DOTNET_的环境变量)
  • 为应用配置设置 以“appsettings.json”和“appsettings.{env.EnvironmentName}.json”作为配置源;同时也将环境变量加入到应用的配置源;最后将命令行参数加入到配置源
  • 配置日志
  • 若是开发模式,还会配置依赖注入的范围验证

四、从使用者的角度来说

通过自定义实现IHostedService的类来实现我们的服务,我们的服务中的类可以

  • 直接使用依赖注入,
  • 也可以通过依赖注入获取主机配置和全局应用配置对象,或者更方便的是进一步使用选项模式
  • 我们也可以注入日志记录器
  • 由于主机创建过程的相关数据几乎都放进了IOC容器中,因此我们也可以通过依赖注入拿到
  • 其它...

在Program.man调用Host.CreateDefaultBuilder,如果需要,提供相应的委托来注册服务和设置主机和应用的“配置源”,最好是通过相关扩展方法和自定义扩展方法。重点是记得注入我们自己的服务实现类

五、总结

.net core为我们提供了新的承载应用(包括但不仅限于asp.net core)的方式-->通用主机,通过它我们可以很容易的在自己的应用中使用依赖注入、配置、日志等,你可以发挥想象实现很多牛B的框架。
asp.net core 3.x开始默认也是使用它来承载的
核心的Host、HostBuilder、Host.CreateDefaultBuilder实现了通用主机,并提供了扩展点

最后我想说如果在.net core上提供一个默认的aop方案就更完美了。
下一篇试试说下asp.net core是如何承载到通用主机上的

asp.net core 3.x 通用主机原理及使用的更多相关文章

  1. asp.net core 3.x 通用主机是如何承载asp.net core的-上

    一.前言 上一篇<asp.net core 3.x 通用主机原理及使用>扯了下3.x中的通用主机,刚好有哥们写了篇<.NET Core 3.1和WorkerServices构建Win ...

  2. asp.net core 系列 17 通用主机 IHostBuilder

    一.概述 ASP.NET Core 通用主机 (HostBuilder),该主机对于托管不处理 HTTP 请求的应用非常有用.通用主机的目标是将 HTTP 管道从 Web 主机 API 中分离出来,从 ...

  3. 翻译 - ASP.NET Core 基本知识 - 通用主机 (Generic Host)

    翻译自 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-5.0 ...

  4. asp.net core 系列 16 Web主机 IWebHostBuilder

    一.概述 在asp.net core中,Host主机负责应用程序启动和生存期管理.host主机包括Web 主机(IWebHostBuilder)和通用主机(IHostBuilder).Web 主机是适 ...

  5. .NET Core 中的通用主机和后台服务

    简介 我们在做项目的时候, 往往要处理一些后台的任务. 一般是两种, 一种是不停的运行,比如消息队列的消费者.另一种是定时任务. 在.NET Framework + Windows环境里, 我们一般会 ...

  6. .Net Core中的通用主机(一)——系统配置

    ASP.NET Core 2.0 中的 WebHost(实现 IWebHost 的基类)是用于为进程提供 HTTP 服务器功能的基础结构项目,例如,如果正在实现 MVC Web 应用或 Web API ...

  7. .Net Core中的通用主机(二)——托管服务

    前文介绍了.Net core的通用主机的配置,在基础配置完成后,下一步就是注册我们的后台任务了..net core提供了一个通用的后台服务接口IHostedService,称为托管服务.一个注册托管服 ...

  8. 翻译 - ASP.NET Core 基本知识 - Web 主机 (Web Host)

    翻译自 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host?view=aspnetcore-5.0 ASP. ...

  9. Asp.Net Core EndPoint 终点路由工作原理解读

    一.背景 在本打算写一篇关于Identityserver4 的文章时候,确发现自己对EndPoint -终结点路由还不是很了解,故暂时先放弃了IdentityServer4 的研究和编写:所以才产生了 ...

随机推荐

  1. @bzoj - 4922@ [Lydsy1706月赛]Karp-de-Chant Number

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 卡常数被称为计算机算法竞赛之中最神奇的一类数字,主要特点集中于令 ...

  2. Top 10 open source projects of 2015

    Top 10 open source projects of 2015 Posted 15 Dec 2015Jen Wike Huger (Red Hat)Feed 188 up 31 comment ...

  3. cp拷贝

    1 cp 拷贝.复制 NAME cp - copy files and directories SYNOPSIS cp [OPTION]... [-T] SOURCE DEST        -- c ...

  4. javascript和jquery 移除事件 和 改变样式

    javascript移除事件: document.getElementById("word").onmouseover = null; javascript改变样式: docume ...

  5. Python--day21--异常处理

    初识try: except -->异常处理 万能异常的用法:except Exception as error:

  6. [转]在eclipse中,用maven创建一个web项目工程

    1.在eclipse中用maven创建项目,右键new>>Maven Project 2.点击next继续 3.点击next继续,选择maven-archetype-webapp, 4.点 ...

  7. P1105 数列

    题目描述 给定一个正整数 \(k(2 \le k \le 15)\) ,把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列,例如,当 \(k = 3\) 时,这个序列是: 1,3,4, ...

  8. 《Spring 5官方文档》 Spring AOP的经典用法

    原文链接 在本附录中,我们会讨论一些初级的Spring AOP接口,以及在Spring 1.2应用中所使用的AOP支持. 对于新的应用,我们推荐使用 Spring AOP 2.0来支持,在AOP章节有 ...

  9. 【js】vue 2.5.1 源码学习 (七) 初始化之 initState 响应式系统基本思路

    大体思路(六) 本节内容: 一.生命周期的钩子函数的实现 ==> callHook(vm , 'beforeCreate') beforeCreate 实例创建之后 事件数据还未创建 二.初始化 ...

  10. 21个项目玩转深度学习:基于TensorFlow的实践详解02—CIFAR10图像识别

    cifar10数据集 CIFAR-10 是由 Hinton 的学生 Alex Krizhevsky 和 Ilya Sutskever 整理的一个用于识别普适物体的小型数据集.一共包含 10 个类别的 ...