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

来源:https://www.cnblogs.com/jionsoft/archive/2020/01/06/12154519.html
-Advertisement-
Play Games

一、前言 只是講asp.net core 3.x通用主機的大致原理,這些東西是通過查看源碼以及自己根據經驗總結得來的,在文章中不會深入源碼,因為個人覺得懂原理就曉得擴展點,後期碰到有需求的時候再仔細去研究源碼也不遲。閱讀前你應該先去瞭解下(推薦博客園老A的博客): asp.net core中的依賴註 ...


一、前言

只是講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是如何承載到通用主機上的

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 當你遇到 一些外國小哥哥小姐姐很心動、想結識交流,但英語水平或其他水平還在提升階段,這個小工具可以幫你渡過難關! Teach you how to flirt gracefully with code 。在本文中,我將詳細講解這個翻譯的具體實現!對於實現的主要功能: 通過微信聊天監聽一些關鍵的口令, ...
  • 1、介面自動化的應用場景 需求穩定 項目周期長 新的項目,先手工測試,然後逐漸開始自動化測試 回歸測試 2、使用Excel 文檔,並以 XXX.xlsx 的格式來管理測試用例數據 自動化用例包括: case_id :用例編號信息 title :用例名稱 url :一部分在配置文件方便修改,一部分在E ...
  • 我們在自動化測試中經常會需要關聯用例處理,需要動態類屬性; 推薦使用第二種方法: 創建:setattr() 獲取:getattr() 兩種,如何創建 類屬性 loan_id # 第一種,創建 # 類名.屬性名 = 具體的屬性值 Context.loan_id = mysql_data.get('Id ...
  • 效果: 步驟: 對著某個標簽頁單擊右鍵,選擇Split Vertically或者Split Horizontally即可。 ...
  • 常量池(也稱常量表):主版本號之後就是常量池的開始位置;java類所對應的常量池主要由常量池數量和常量池數組兩部分組成,常量池數量是主版本號之後的兩個位元組;常量池數組在常量池數量之後,常量池數組中不同元素的類型,結構是不同的,所以該數組長度是不同的,但是數組中的每一種元素的第一個位元組是標記位是一個u... ...
  • SqlSessionFactory SqlSessionFactory是單個資料庫映射關係經過編譯後的記憶體鏡像,主要作用是創建SqlSession。 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml ...
  • 我們經常會從網路上下載一些帶密碼的壓縮包,想要獲取裡面的內容,往往就要給提供商支付一些費用。想要白嫖其中的內容,常見的做法是百度搜索一些壓縮包密碼破解軟體,但後果相信體驗過的人都知道。本文將會利用 Python 破解壓縮包的密碼,這裡以 ZIP/RAR 為例。 ! 破解原理 其實原理很簡單,一句話概 ...
  • 為什麼Python使用縮進來分組語句? 為什麼簡單的算術運算得到奇怪的結果? 為什麼浮點計算不准確? 為什麼Python字元串是不可變的? 為什麼必須在方法定義和調用中顯式使用“self”? 為什麼不能在表達式中賦值? 為什麼Python對某些功能(例如list.index())使用方法來實現,而其 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...