asp.net core 3.x 通用主機原理及使用

1、前言

只是講asp.net core 3.x通用主機的大體原理,這些東西是經過查看源碼以及本身根據經驗總結得來的,在文章中不會深刻源碼,由於我的以爲懂原理就曉得擴展點,後期碰到有需求的時候再仔細去研究源碼也不遲。
閱讀前你應該先去了解下(推薦博客園老A的博客):web

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

講解的方式是:json

  1. 概述
  2. 逐一介紹核心類及擴展方式
  3. 一般咱們如何使用
  4. 總結

2、概述

 

 

之前的控制檯應用程序、winform程序啓動時main首先被執行,後續都是咱們本身的代碼來實現框架和業務上的東東,好比咱們要使用配置就ConfigurationManager.AppSettings... 若想使用依賴注入則須要引入第三方框架,好比autofact。asp.net framework時代也相似後端

在.net core 3.0以前的版本默認使用的是IWebHost,它內部定義了IOC容器(服務註冊體如今Startup.ConfigServices),和各類配置源的設置(體如今Program配置主機時),咱們後續的Controler、View、包括業務代碼能夠很容易作依賴注入和獲取配置信息(包括運用選項模式)api

有時候咱們但願寫一個服務,可是這個服務並非用來作api/web,處理http請求的,好比想作一個物聯網的後端採集服務,一直等待遠端硬件設備提交實時數據過來,後端進行處理。可是又但願使用asp.net core提供的 配置、依賴注入、日誌 和其它功能。後來微軟就將asp.net core中的這套東西抽離出來了,叫作通用主機,用來承載任何服務,這些自定義服務中就能夠很方便地使用配置、依賴注入、日誌、和其它功能。如今asp.net core只是由通用主機承載的其中一種服務。mvc

2.一、默認狀況下主要的實現思路是:

2.1.一、定義(微軟定義好的):

  • 定義HOST,它包含IOC根容器、主機和應用程序的生命週期事件定定義、IHostedService集合(一個實例就是一個服務或者叫應用,asp.net core就是一個這樣的實例)
  • 容許調用方提供一堆委託來向IOC中註冊服務、和設置主機和應用的「配置源」
  • 提供向主機添加IHostedService的實現對象的方法
  • 容許調用方註冊主機和應用在啓動和中止階段觸發的相應事件

2.1.二、配置(咱們的代碼,微軟定義不少輔助方法):

  • 建立IHost實例
  • 向Host的IOC容器中註冊各類服務
  • 配置主機和應用程序的「配置源
  • 向主機內部添加IHostedService實例(也就是咱們最終的服務)
  • 主機和應用的生命週期事件,來實現一些特殊任務

2.1.三、啓動階段(微軟定義好的)

  • 上面所謂的配置基本都是經過委託實現的(一般微軟提供的各類擴展方法最終也是執行委託),回調這些委託以設置「配置源」和註冊服務
  • 最後遍歷啓動HostedService
  • 在啓動過程當中還會回調相應的生命週期事件

2.二、啥是應用?

上面提了幾回「應用」,如今對於主機來講asp.net core框架就是一個應用、咱們上面舉例說的"物聯網後端服務"是另外一個應用。從代碼上來講就是一個IHostedService的實現。
主機和應用是一對多的關係,多個應用能夠共享主機的信息,如:主機的IOC容器、主機的配置。應用配置。應用固然也能夠本身去建立本身的IOC根容器和配置對象app

主機配置和應用配置有關係?這兩個配置對象都存在於Host中,主機配置是隻跟主機相關的配置,應用配置是主機中多個應用共享的配置,若是主機中只有一個應用,那麼徹底能夠拿它作最終的應用配置。另外應用配置包含主機配置框架

注意:在理解時要記住咱們如今的目的是講解通用主機,意思是能夠承載你本身定義的服務的主機,別去想什麼mvc controller action 路由之類的asp.net

3、核心類

下面分別介紹下主機中的幾個核心默認實現類,幾乎每一個類都有對應的接口,爲了縮短篇幅、便於理解就不講接口了。ide

3.一、Host

它表明主機,用來宿主(承載)咱們應用(一個IHostedService的實現)。
主要包含:日誌、主機和應用的生命週期事件、IOC根容器、主機的選項對象、啓動中止/中止方法。
接口中只定義了:IOC根容器 + Start + Stop方法
它在Program.Main中被建立、配置和啓動ui

默認實現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.二、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.三、HostBuilder的工廠方法Host.CreateDefaultBuilder

上面有了Host,也有了對應的建立器HostBuilder,爲啥還要再提供一個工廠方法呢?
由於職責分離原則,Host只負責承載應用並提供容器和設置配置源;HostBuilder只是負責配置並建立Host,儘量提供一些默認值(前提時未來調用方未提供那些參數)。此時咱們能夠直接用HostBuilder來建立Host並啓動它,但別忘了.net core是一個通用框架,它應提供一個更簡潔的方式來建立最終的Host,所以它提供了靜態方法Host.CreateDefaultBuilder,它儘量提供更多的默認值,核心任務以下:

  • new HostBuilder
  • 設置程序的當前目錄爲內容根
  • 爲主機配置 設置 環境變量做爲配置源(只關注前綴DOTNET_的環境變量)
  • 爲應用配置設置 以「appsettings.json」和「appsettings.{env.EnvironmentName}.json」做爲配置源;同時也將環境變量加入到應用的配置源;最後將命令行參數加入到配置源
  • 配置日誌
  • 如果開發模式,還會配置依賴注入的範圍驗證

4、從使用者的角度來講

經過自定義實現IHostedService的類來實現咱們的服務,咱們的服務中的類能夠

  • 直接使用依賴注入,
  • 也能夠經過依賴注入獲取主機配置和全局應用配置對象,或者更方便的是進一步使用選項模式
  • 咱們也能夠注入日誌記錄器
  • 因爲主機建立過程的相關數據幾乎都放進了IOC容器中,所以咱們也能夠經過依賴注入拿到
  • 其它...

在Program.man調用Host.CreateDefaultBuilder,若是須要,提供相應的委託來註冊服務和設置主機和應用的「配置源」,最好是經過相關擴展方法和自定義擴展方法。重點是記得注入咱們本身的服務實現類

5、總結

.net core爲咱們提供了新的承載應用(包括但不只限於asp.net core)的方式-->通用主機,經過它咱們能夠很容易的在本身的應用中使用依賴注入、配置、日誌等,你能夠發揮想象實現不少牛B的框架。
asp.net core 3.x開始默認也是使用它來承載的
核心的Host、HostBuilder、Host.CreateDefaultBuilder實現了通用主機,並提供了擴展點

最後我想說若是在.net core上提供一個默認的aop方案就更完美了。
下一篇試試說下asp.net core是如何承載到通用主機上的

相關文章
相關標籤/搜索