抽絲剝繭讀源碼——Microsoft.Extensions.Configuration(1)

来源:https://www.cnblogs.com/boydenyol/archive/2020/04/25/12775255.html
-Advertisement-
Play Games

開題 ​ 既然決定了開始寫博客,那就從讀ASP.NET core的源碼開始吧!對於我這個不怎麼善於寫文章的人來說,也算是鍛煉鍛煉自己歸納總結能力。 千里之行,始於足下 ​ 俗話說,“千里之行,始於足下”,我們先看看ASP.NET core的 是如何使用的。為了方便說明,這裡建立的 的測試工程,使用 ...


開題

​ 既然決定了開始寫博客,那就從讀ASP.NET core的源碼開始吧!對於我這個不怎麼善於寫文章的人來說,也算是鍛煉鍛煉自己歸納總結能力。

千里之行,始於足下

​ 俗話說,“千里之行,始於足下”,我們先看看ASP.NET core的Configuration是如何使用的。為了方便說明,這裡建立的xunit的測試工程,使用nuget下載Microsoft.Extensions.Configuration包:

var dc = new Dictionary<string, string>
{
	{"SectionA", "ValueA" },
	{"SectionB", "ValueB" }
};
var builder = new ConfigurationBuilder().AddInMemoryCollection(dc);
var configurationRoot = builder.Build();
Assert.Equal("ValueA", configurationRoot["SectionA"]);
Assert.Equal("ValueB", configurationRoot["SectionB"]);

​ 最簡單的幾行代碼,可以看出配置文件最基本的使用流程。

構建一個ConfigurationBuilder對象

添加配置資源(這裡使用的是InMemoryCollection)

最後使用Build()方法生成IConfigurationRoot配置對象

使用IConfigurationRoot對象獲取配置信息

​ 這裡我們從這段代碼中能看出ConfigurationBuilder是繼承了IConfigurationBuilder這個介面,它Build出來的對象繼承了IConfigurationRoot介面,IConfigurationRoot又繼承了IConfiguration介面,而這些介面都位於Microsoft.Extensions.Configuration.Abstractions這個程式集中。

​ 那就從這裡開始抽絲剝繭,深入探究下配置部分的源碼吧!請從Github下載好源碼。

https://github.com/aspnet/Configuration => https://github.com/dotnet/extensions

​ 你是不是發現最新的src文件夾下根本沒有我們想要的Microsoft.Extensions等源碼呀!我們需要切換到v3.1.3或以下的版本然後下載對應版本的代碼就好了。為了更方便調試代碼,我建議還是將代碼從Github的倉庫clone下來,構建源碼也比較簡單。

git clone https://github.com/dotnet/extensions.git

git checkout v3.1.2

restore.cmd

build.cmd

Microsoft.Extensions.Configuration.Abstraction開始

​ 不說廢話,上圖:

​ 從上圖可以看出我們的IConfigurationBuilder中包含一個IList<IConfigurationSource>對象和Add(IConfigurationSource source)方法 ,這意味著ASP.NET core的配置對象是支持多配置源的。 IConfigurationBuilder通過Build方法,生成一個IConfigurationRoot對象,可通過實現父介面IConfiguration的索引器this[string key]獲取到配置信息。對於IConfigurationProvider對象和IConfigurationSection我們通過對抽象的實現去探索。

進入Microsoft.Extensions.Configuration

ConfigurationBuilder
	`Build`方法最終生成了`ConfigurationRoot`對象,並初始了`List<IConfigurationProvider>`。
public IConfigurationRoot Build()
{
	var providers = new List<IConfigurationProvider>();
	foreach (var source in Sources)
	{
		var provider = source.Build(this);
		providers.Add(provider);
	}
	return new ConfigurationRoot(providers);
}

​ 而IConfigurationProvider是由IConfigurationSourcebuild生成的。

public IConfigurationBuilder Add(IConfigurationSource source)
{
	if (source == null)
	{
		throw new ArgumentNullException(nameof(source));
	}
	Sources.Add(source);
	return this;
}
ConfigurationRoot

​ 那配置信息時如何載入進去的呢?

​ 我們先看下配置信息是如何讀取的,在索引器的get方法中,數據時是從provider中獲取到的,而且在所有的_providers中倒序查找到provider後就會退出查找,這也意味著我們在添加多個配置源時,最後添加的配置源會覆蓋之前添加的配置源,當然這是在鍵值相同的情況下。

public string this[string key]
{
	get
	{
		for (var i = _providers.Count - 1; i >= 0; i--)
		{
			var provider = _providers[i];
			if (provider.TryGet(key, out var value))
				return value;
		}
		return null;
	}
    set...
}

​ 那provider的數據是從哪裡來的呢?在ConfigurationProvider這個類中,可以看到所有的數據都來源於Data這個Dictionary<string, string>字典集合。

​ 這個字典集合是什麼時候載入的呢?

public virtual bool TryGet(string key, out string value) 
	=> Data.TryGetValue(key, out value);

​ 在構造ConfigurationRoot對象時,我們看到所有的provider對象都調用了Load()方法。在ConfigurationProvider類中Load()方法是虛方法,且沒有找到別的地方對Data這個變數進行賦值,那麼這個時候可以猜想ConfigurationProvider繼承類會重寫這個方法,載入Data的值,那麼我們去MemoryConfigurationProvider這個類中去驗證一下,MemoryConfigurationProvider在構造函數中完成了Data的賦值,沒有重寫這個方法。汗~~~

public ConfigurationRoot(IList<IConfigurationProvider> providers)
{
    if (providers == null)
	{
		throw new ArgumentNullException(nameof(providers));
	}
    _providers = providers;
	_changeTokenRegistrations = new List<IDisposable>(providers.Count);
    foreach (var p in providers)
	{
		p.Load();
		_changeTokenRegistrations.Add(ChangeToken.OnChange(() =>p.GetReloadToken(),
    	() => RaiseChanged()));
	}
}

​ 那在這裡先去漫游一下,通過FileConfigurationProvider => JsonConfigurationProvider找到了Data = JsonConfigurationFileParser.Parse(stream),證明我們的猜想還是沒有錯的。

​ 這麼一路抽絲剝繭,我們就知道了配置信息是如何運作的了!下一步我們看看配置文件是如何監視文件變化的,也對FileConfigurationProvider這一部分細化閱讀一下。


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

-Advertisement-
Play Games
更多相關文章
  • 1. 打開 Container Station 2. 點擊左側 屬性 ,切換到 Registry伺服器 ,點擊 新增 ,如下圖 " " 3. 填寫鏡像信息,網址:https://p31wiatp.mirror.aliyuncs.com ,填寫完後,記得點擊一下 測試 ,驗證一下網路是否暢通,一般是可 ...
  • 大家在應聘的時候,特別需要註意的是公司的任職要求,也就是招聘標準,有時候不是你不行,而是你與公司需求不匹配。下麵的言論來自學姐昨天的朋友圈: ​ “知己知彼,方能百戰百勝”。而基本上所有互聯網公司的技術,都是BAT等領軍企業技術的跟隨者。 所以,瞭解BAT等一線互聯網的任職要求,顯得十分的重要,下麵 ...
  • 因為使用重定向的跳轉方式的情況下,跳轉到的地址無法獲取 request 中的值。 很好的解決了這個問題。 1. redirectAttributes.addAttributie("param", value); 這種方法相當於在重定向鏈接地址追加傳遞的參數。以上重定向的方法等同於 ,註意這種方法直接 ...
  • 在 SpringMVC 中,可以指定畫面的跳轉方式。使用 首碼實現請求轉發跳轉,使用 首碼實現重定向跳轉。有首碼的轉發和重定向操作和配置的視圖解析器沒有關係,視圖解析器不會進行拼串。 請求轉發首碼—forward: 使用請求轉發跳轉方式,url 地址不會改變,一次請求一次相應,跳轉到的地址可以獲得 ...
  • 面試題51. 數組中的逆序對 題目來源: "https://leetcode cn.com/problems/shu zu zhong de ni xu dui lcof/" 題目 在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的 ...
  • 首先我們來看解封裝: >>> mytuple=3,4,5 >>> mytuple (3, 4, 5) 這將 3,4,5 封裝到元組 mytuple 中。 現在我們將這些值解封裝到變數 x,y,z 中: >>> x,y,z=mytuple >>> x+y+z 得到結果12.結語 本文首發於python ...
  • 0. 前言 上一篇內容介紹了Console類和Math類,這篇內容著重介紹一下C 中時間日期的處理方式。 上一篇勘誤: 上一篇中關於靜態類沒有構造函數,這一表述有誤。正確的說法是C 中靜態類不包含常規構造函數,但可以添加一個靜態構造函數。 靜態構造函數與普通普通構造函數的區別是,靜態構造函數沒有訪問 ...
  • 前言: 這是 項目實踐系列 , 算是中高級系列博文, 用於為項目開發過程中不好解決的問題提出解決方案的. 不屬於入門級系列. 解釋起來也比較跳躍, 只講重點. 因為有網友的項目需求, 所以提前把這些解決方案做出來並分享. 問題: Blazor自己是攜帶一個簡單的路由功能的, 當切換Url的時候, 整 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...