日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

抽丝剥茧读源码——Microsoft.Extensions.Configuration(2)

發布時間:2023/12/13 综合教程 25 生活家
生活随笔 收集整理的這篇文章主要介紹了 抽丝剥茧读源码——Microsoft.Extensions.Configuration(2) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

繼續抽絲剝繭

? 我們知道在使用jsonxmlini等文件類配置源時,如果更改了配置文件中的內容,程序是能夠感知文件變化的。這里以json配置源為例,查看AddJsonFile這個方法的定義,我們看到在添加json配置源的時候,有這么兩個參數:

AddJsonFile(this IConfigurationBuilder builder, 
            string path, bool optional, bool reloadOnChange);

optional:配置文件可選

reloadOnChange:配置文件修改時進行重新加載

? OK,動手操練操練。

test.json文件:

{
  "SectionA": "ValueA",
  "SectionB": "ValueB"
}

測試代碼:

var builder = new ConfigurationBuilder().AddJsonFile("test.json",false,true);
IConfigurationRoot configurationRoot = builder.Build();
Assert.Equal("ValueA", configurationRoot["SectionA"]);
Assert.Equal("ValueB", configurationRoot["SectionB"]);
Thread.Sleep(3000);  //這時將文件中SectionA的值更改為ValueA+
Assert.Equal("ValueA+", configurationRoot["SectionA"]);

? 完美通過測試。那么,配置信息是如何監視文件變化的呢?

CancellationTokenSource的使用

? 為了弄清楚配置信息是如何監視文件變化之前,我們先看下CancellationTokenSource的簡單應用。

var source = new CancellationTokenSource();
source.Token.Register(() => Console.WriteLine("This is a callback"));
if(!source.IsCancellationRequested)
{
	source.Cancel();
}
// 控制臺輸出 "This is a callback"

? CancellationTokenSource多用在取消線程操作中,這里使用了CancellationToken注冊回調的特性,使用Cancel()方法時觸發回調函數。配置文件的重加載就是通過這個原理實現的,所以在接下來IChangeToken接口的實現類中,我們就能發現CancellationTokenSource的身影。

引入FileExtension

? 目前我們引入了文件配置源,并使用json文件作為了測試文件,那我們再把之前的圖再補充一下。

ConfigurationRoot

? 追溯一下我們在加載配置源時的代碼。

//private readonly IList<IDisposable> _changeTokenRegistrations;
foreach (var p in providers)
{
	p.Load();
	_changeTokenRegistrations.Add(ChangeToken.OnChange(() =>p.GetReloadToken(),
	() => RaiseChanged()));
}

? 我們看到了_changeTokenRegistrations這個對象調用了ChangeToken.OnChange()靜態方法,那么這個靜態方法做了什么呢?

public static IDisposable OnChange(Func<IChangeToken> changeTokenProducer, Action changeTokenConsumer)
{
	if (changeTokenProducer == null)
	{
		throw new ArgumentNullException(nameof(changeTokenProducer));
	}
	if (changeTokenConsumer == null)
	{
		throw new ArgumentNullException(nameof(changeTokenConsumer));
	}
	return new ChangeTokenRegistration<Action>(changeTokenProducer, callback => callback(), changeTokenConsumer);
}

? 這里引入了ChangeTokenRegistration這個類,通過類的構造函數參數(Func<IChangeToken> changeTokenProducer, Action<TState> changeTokenConsumer, TState state),我們可以看出

它就是將token的生產者changeTokenProducer和消費者changeTokenConsumer做一個綁定操作,綁定的消費函數就是ConfigurationRoot中的RaiseChanged()函數。

private void RaiseChanged()
{
	var previousToken = Interlocked.Exchange(ref _changeToken, new ConfigurationReloadToken());
	previousToken.OnReload();
}

? 通過這個函數就看到previousToken執行了OnReload()函數,這里我們再跟蹤到此函數的定義時,我們就發現了這段代碼。

public void OnReload() => _cts.Cancel();

? 是不是有點清晰了,但是通過CancellationTokenSource的使用我們知道,token是需要綁定callback函數的,那么這個注冊是在哪里進行的呢?我們再回到ChangeTokenRegistration這個類中。

private void OnChangeTokenFired()
{
	// The order here is important. We need to take the token and then apply our changes BEFORE
	// registering. This prevents us from possible having two change updates to process concurrently.
	// If the token changes after we take the token, then we'll process the update immediately upon
	// registering the callback.
	var token = _changeTokenProducer();
	try
	{
		_changeTokenConsumer(_state);
	}
	finally
	{
		// We always want to ensure the callback is registered
		RegisterChangeTokenCallback(token);
	}
}

? 在ChangeTokenRegistration的構造函數中,我們知道token注冊了OnChangeTokenFired()這個函數回調,這個函數主要做了三件事情:

token生產者生產一個新的token

消費token,觸發消費函數

將新的token重新注冊一個到此回調函數

? 這樣在token失效后又被重新注冊了。

? 但是,但是,但是,重要的事情說三遍。這里還不是監視文件變化部分的原理哦,這里只是多配置源用來監視配置文件重載的,那么監視文件變化其實也是這個原理,這里理順了,文件變化只要找到使用ChangeToken.OnChange()這個靜態方法的地方就可以了,文件變化也就理解了。

FileConfigurationProvider

? 在FileConfigurationProvider類的構造函數中,我們就找到了監視文件變化的源頭了。這里的消費者函數,就是Load()函數,一旦監視到文件變化就調用Load對文件進行重新加載。

if (Source.ReloadOnChange && Source.FileProvider != null)
{
	_changeTokenRegistration = ChangeToken.OnChange(
	() => Source.FileProvider.Watch(Source.Path),
	() => {
			Thread.Sleep(Source.ReloadDelay);
			Load(reload: true);
	});
}

? 這里的Watch函數用到的原理是FileSystemWatcher這個類,這里不過多闡述,大家可自行查看,它主要有以下幾個事件.

public event FileSystemEventHandler Deleted

public event FileSystemEventHandler Created

public event FileSystemEventHandler Changed

public event RenamedEventHandler Renamed

public event ErrorEventHandler Error;

? 配置文件方面的原理也就逐漸清晰了,不過原理易懂,設計思想難懂,希望大家多借鑒其中的設計理念,用好別人的代碼,也寫好自己的代碼。
個人博客:www.corecoder.cn

總結

以上是生活随笔為你收集整理的抽丝剥茧读源码——Microsoft.Extensions.Configuration(2)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 最新av免费| 国产在线一二区 | 国产精品成人一区二区 | 国产人成一区二区三区影院 | 国产精品剧情 | 黄片毛片在线 | 精品国模一区二区三区欧美 | 欧美在线网站 | 午夜在线看| 日韩精品人妻中文字幕 | 成人激情电影在线观看 | 国产欧美亚洲一区二区 | 免费看大片a | 人与动物黄色片 | 欧美精品videos另类日本 | 日本三级播放 | 青娱乐国产 | 肉嫁高柳在线 | 黑人黄色片 | 一区二区三区丝袜 | 成人亚洲免费 | 国产激情综合 | 伊人五月天 | 国产欧美一区二区 | 一区二区三区精品视频 | 亚洲激情在线视频 | 日本大尺度电影免费观看全集中文版 | 97干干 | 亚洲精品视频在线观看免费 | 欧美黄色影院 | 最新不卡av | 国产成年视频 | 一区二区视 | 综合久久激情 | 亚洲国产精品成人综合在线 | heyzo北岛玲在线播放 | 激情五月视频 | 日韩亚州| 青青草免费公开视频 | 欧美性受xxxxxx黑人xyx性爽 | av色站| 500福利视频导航 | 天堂视频在线观看免费 | 黑人玩弄人妻一区二区绿帽子 | 韩国伦理在线视频 | 色哟哟在线视频 | 蜜桃久久一区二区三区 | 亚洲高清网站 | 91久久精品无码一区二区 | 日本高清xxx | 日本一二三视频 | 亚洲一区二区三区人妻 | 寡妇av | 在线观看黄色小视频 | 九色国产在线 | 操人视频免费 | 欧美黑人性受xxxx精品 | 伊人久色 | 亚洲精品v | 精品91在线| 明日花绮罗高潮无打码 | 大肉大捧一进一出好爽视频动漫 | 变态另类ts人妖一区二区 | 97人人模人人爽人人少妇 | 国产精品一区二区无码对白 | 午夜成人免费电影 | 精品国产三级a∨在线 | 你懂的在线观看视频 | 看黄色的网址 | 美国黄色一级毛片 | 91亚洲精品久久久蜜桃 | 日韩少妇内射免费播放18禁裸乳 | 久久伊人操 | 婷婷五月综合激情 | 在线国产区 | 操操操操操操操 | 亚洲AV成人无码精品久久盆瓶 | 91蝌蚪91九色白浆 | 91pao| 毛片在线网站 | 日韩精品久久久久久久电影99爱 | 久久在草| 波多野结衣一本一道 | www.色人阁.com| 亚洲国产精品成人综合在线 | 国产femdom调教7777 | 特级精品毛片免费观看 | 亚洲精品字幕在线 | 成年网站免费在线观看 | 国产精品区二区三区日本 | 天天综合网永久 | 欧美综合日韩 | 国产又黄又 | 亚洲乱码少妇 | 日本久久久久久久久久 | 色女人av | 欧洲亚洲一区 | 性欧美大战久久久久久久 | 88av在线播放 |