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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Dotnet 6.0 深度探索(一)

發布時間:2023/12/4 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Dotnet 6.0 深度探索(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Dotnet 6.0 已來。

Dotnet 6.0 大家都裝了沒?

我打算開個專題,系統地寫一寫 Dotnet 6.0 在各個方面的特性,以及全新的開發方式。也是因為最近討論 6.0 比較多,看到很多人的畏難情緒,所以打算寫寫相關的內容。

了解了,就不怕了。

要寫的內容很多,我會分幾篇來寫。

今天是第一篇:ConfigurationManager,配置管理器。

ConfigurationManager 是干什么用的?

引用微軟官方的說法:ConfigurationManager 是用來支持 ASP.Net Core 的新的 WebApplication 模型。這個模型主要的作用是在一些特定的場景下(后面我們會說到),用來簡化 ASP.NET Core 的啟動代碼。

當然,如果我們去看 MSDN 的文檔,會發現 ConfigurationManager 本身實現還是挺復雜的。好在,大多數情況下,這是一個半隱藏的東西,你可能都意識不到你已經用到了它。

那它到底是干什么用的?

這得從 .Net 5.0 的 Configuration 說起。

.Net 5.0 里的 Configuration

Configuration 配置,從 3.1 到 5.0,增加了很多很多的配置類型,如果你去 MSDN 上看,有好幾大篇。

這里面,我們接觸最多的是兩個:

  • IConfigurationBuilder - 這個接口主要用來增加配置源,并在構建器上調用 Build() 來讀取每個配置源,并形成最終的配置

  • IConfigurationRoot - 這就是上面 Build() 完成后形成的配置,我們會從這里面讀配置值

在實際應用中,IConfigurationBuilder 通常被我們用做配置源列表的包裝器,最常用的是通過 AddJsonFile(),將配置源添加到源列表中。看到 AddJsonFile(),你是不是想到了什么?

簡單來說,IConfigurationBuilder 是這樣的:

public?interface?IConfigurationBuilder {IDictionary<string,?object>?Properties?{?get;?}IList<IConfigurationSource>?Sources?{?get;?}IConfigurationBuilder?Add(IConfigurationSource?source);IConfigurationRoot?Build(); }

而 IConfigurationRoot,里面放的是經過合并的配置值。這個合并需要注意一下,多個配置源逐個加入時,相同名稱的項,后面的配置會覆蓋前面的項。

在 .Net 5.0 以前,IConfigurationBuilder 和 IConfigurationRoot 接口分別由 ConfigurationBuilder 和 ConfigurationRoot 實現。使用時通常是這么寫:

var?builder?=?new?ConfigurationBuilder();//?加入靜態值 builder.AddInMemoryCollection(new?Dictionary<string,?string> {{?"MyKey",?"MyValue"?}, });//?加入文件 builder.AddJsonFile("appsettings.json");IConfigurationRoot?config?=?builder.Build();string?value?=?config["MyKey"];?//?取一個值 IConfigurationSection?section?=?config.GetSection("SubSection");?//?取一個節

這是在 Console 程序中。

在 ASP.NET Core 中,通常不需要這么顯式的 new 和 Build(),但事實上也是調用的這個接口。

在默認的 ConfigurationBuilder 實現中,調用 Build() 將遍歷所有的源,加載 Provider 程序,并將它們傳遞給一個新的ConfigurationRoot 實例:

public?IConfigurationRoot?Build() {var?providers?=?new?List<IConfigurationProvider>();foreach?(IConfigurationSource?source?in?Sources){IConfigurationProvider?provider?=?source.Build(this);providers.Add(provider);}return?new?ConfigurationRoot(providers); }

然后,ConfigurationRoot 依次遍歷每個提供程序并加載配置值:

public?class?ConfigurationRoot?:?IConfigurationRoot,?IDisposable {private?readonly?IList<IConfigurationProvider>?_providers;private?readonly?IList<IDisposable>?_changeTokenRegistrations;public?ConfigurationRoot(IList<IConfigurationProvider>?providers){_providers?=?providers;_changeTokenRegistrations?=?new?List<IDisposable>(providers.Count);foreach?(IConfigurationProvider?p?in?providers){p.Load();_changeTokenRegistrations.Add(ChangeToken.OnChange(()?=>?p.GetReloadToken(),?()?=>?RaiseChanged()));}}//?...? }

這種架構,會有個小問題。在團隊開發的時候,在沒有統一溝通的情況下,有可能會在多處調用 Build()。當然這也沒什么問題。只不過,正常來說這個沒有必要,畢竟這是在讀文件,會很慢。

不過,在 .Net 5.0 之前,都是這么做。

可喜的是,在 .Net 6.0 里,微軟也注意到這個問題,并引入了一個新的類型:ConfigurationManager。

.Net 6.0 里的 ConfigurationManager

ConfigurationManager 是一個 .Net 6.0 中新的配置類型。這個類型也同樣實現了兩個接口:IConfigurationBuilder 和 IConfigurationRoot。那么,通過這兩個接口的實現,我們可以簡化上一節講到的 .Net 5.0 中的通用模式。

不過,還是有一點點區別。這里 IConfigurationBuilder 將源保存為 IList:

public?interface?IConfigurationBuilder {IList<IConfigurationSource>?Sources?{?get;?}//?... }

這樣做有一個好處,就是對于源 IList,就有了 Add() 和 Remove() 方法,我們可以在不知道 ConfigurationManager 的情況下增加和刪除配置提供程序。

private?class?ConfigurationSources?:?IList<IConfigurationSource> {private?readonly?List<IConfigurationSource>?_sources?=?new();private?readonly?ConfigurationManager?_config;public?ConfigurationSources(ConfigurationManager?config){_config?=?config;}public?void?Add(IConfigurationSource?source){_sources.Add(source);_config.AddSource(source);?//?增加源}public?bool?Remove(IConfigurationSource?source){var?removed?=?_sources.Remove(source);?//?刪除源_config.ReloadSources();?//?重新加載源return?removed;}//?...? }

這樣做可以確保 ConfigurationManager 在改變源的 IList 時,能自動加載源的配置數據。

看一下 ConfigurationManager.AddSource 的定義:

public?class?ConfigurationManager {private?void?AddSource(IConfigurationSource?source){lock?(_providerLock){IConfigurationProvider?provider?=?source.Build(this);_providers.Add(provider);provider.Load();_changeTokenRegistrations.Add(ChangeToken.OnChange(()?=>?provider.GetReloadToken(),?()?=>?RaiseChanged()));}RaiseChanged();} }

這個方法會立即調用 IConfigurationSource 的 Build() 方法來創建 IConfigurationProvider,并加入到源列表中。

下面,這個方法就調用 IConfigurationProvider 的 Load() 方法,將數據加載到 Provider。

這個方法解決了一件事,就是當我們需要從不同的位置向 IConfigurationBuilder 加入各種源時,源只需要加載一次,而且只會加載一次。

上面的代碼是增加源。當我們需要 Remove() 源,或者干脆清除掉全部的源 Clear() 時,就需要調用 ReloadSource():

private?void?ReloadSources() {lock?(_providerLock){DisposeRegistrationsAndProvidersUnsynchronized();_changeTokenRegistrations.Clear();_providers.Clear();foreach?(var?source?in?_sources){_providers.Add(source.Build(this));}foreach?(var?p?in?_providers){p.Load();_changeTokenRegistrations.Add(ChangeToken.OnChange(()?=>?p.GetReloadToken(),?()?=>?RaiseChanged()));}}RaiseChanged(); }

當然,看懂上面的代碼,也就明白兩件事:

  • 增加源是代碼最小的,加到列表中就行了 ;

  • 刪除或更改源代碼會有點大,需要重新遍歷加載所有源。

  • 如果需要對配置的源進行大量的操作,這樣的代價會比較大。不過,這種情況會很不常見。

    總結一下

    .Net 6.0 引入了一個新的 ConfigurationManager,用來優化配置的構建。

    ConfigurationManager 同樣實現了 ConfigurationBuilder 和 ConfigurationRoot。這算是個兼容性的設置,主要是為了支持 WebHostBuilder 和 HostBuilder 中對配置的調用。同時,也兼容了早期代碼中的調用方式。所以,代碼升級時,相關配置調用的部分,如果不想改代碼,是完全可以的。而如果想做點改動,就換成使用 ConfigurationManager,或者通過 WebApplicationBuilder 來加載(會自動調用 ConfigurationManager),應用程序會有更好的性能。

    這算是一個小禮物,相信也是微軟權衡以后的結果。

    又:寫著寫著,發出這個題目有點大了,要寫的很多,可最近年底了,又有點忙,得容我慢慢寫:P

    喜歡就來個三連,讓更多人因你而受益

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的Dotnet 6.0 深度探索(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

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