在哪个电视频道看欧洲杯直播

admin · 2009-09-01

  

  正在这个系列中,我将追求一下 .NET 6 中的少少新特征。依然有良众对于 .NET 6 的实质,囊括良众来自 .NET 和 ASP.NET 团队自身的著作。正在这个系列中,我将追求一下这些特征当面的少少代码。

  正在这第一篇著作中,来钻探一下 ConfigurationManager 类,讲一下为甚么要新增这个类,并看一下它的的少少实新颖码。

   1甚么是 ConfigurationManager

  倘若你的第一响应是甚么是 ConfigurationManager,那末不必顾虑,你没有错过一个紧张的通告:

  插手 ConfigurationManager 是为了维持 ASP.NET Core 的新 WebApplication 模子,用于简化 ASP.NET Core 的启动代码。但是 ConfigurationManager 正在很大水平上是一个杀青细节。它的引入是为了优化一个特定的场景(我很疾会讲),但正在大家半景况下,你不用要(也不会)领略你正在利用它。

  正在咱们探讨 ConfigurationManager 自身以前,咱们先来看看它所代替的货色和缘由。

   2.NET 5 中的/

  .NET 5 缭绕设备揭示了众品种型,但正在你的行使次第中直接利用的两个合键范例是:

   IConfigurationBuilder - 用来增加设备源。正在构修器上移用 Build() 读取每一个设备源,并构修终极的设备。 IConfigurationRoot - 代外终极构修好的设备。

  IConfigurationBuilder 接口合键是一个缭绕设备源列外的封装器。设备供给者往往囊括扩子(如 AddJsonFile() 和 AddAzureKeyVault()),将设备源增加到 Sources 列外中。

  

publicinterfaceIConfigurationBuilder{IDictionary<string,object>Properties{get;}IList<IConfigurationSource>Sources{get;}IConfigurationBuilderAdd(IConfigurationSourcesource);IConfigurationRootBuild();}

 

  同时,IConfigurationRoot 代外终极层的设备值,团结了每一个设备源的总共值,以供给总共设备值的终极立体视图。

  

  后者设备供给者(情况变量)笼盖了前者设备供给者(appsettings.json、sharedsettings.json)增加的值。

  正在 .NET 5 及从前的版本中,IConfigurationBuilder 和 IConfigurationRoot 接口不同由 ConfigurationBuilder 和 ConfigurationRoot 杀青。倘若你直接利用这些范例,你能够会如许做:

  

varbuilder=newConfigurationBuilder();//addstaticvaluesbuilder.AddInMemoryCollection(newDictionary<string,string>{{"MyKey","MyValue"},});//addvaluesfromajsonfilebuilder.AddJsonFile("appsettings.json");//createtheIConfigurationRootinstanceIConfigurationRootconfig=builder.Build();stringvalue=config["MyKey"];//getavalueIConfigurationSectionsection=config.GetSection("SubSection");//getasection

 

  正在一个规范的 ASP.NET Core 行使次第中,你不会本身创修 ConfigurationBuilder,或移用 Build(),但除此以外,这即是幕后发作的事变。这两品种型之间有显着的散开,况且正在大家半景况下,设备体例运转优秀,那末为甚么咱们正在.NET 6 中必要一个新范例呢?

   3.NET 5 中片面构树立备的题目

  这类计划的合键题目是正在你必要片面构树立备的时刻。当你将设备存储正在 Azure Key Vault 等任事中,乃至是数据库中时,这是一个常睹的题目。

  比方,如下是正在 ASP.NET Core 中的 ConfigureAppConfiguration() 内里从 Azure Key Vault 读取 secrects 的创议方法:

  

.ConfigureAppConfiguration((context,config)=>{//"normal"configurationetcconfig.AddJsonFile("appsettings.json");config.AddEnvironmentVariables();if(context.HostingEnvironment.IsProduction()){IConfigurationRootpartialConfig=config.Build();//buildpartialconfigstringkeyVaultName=partialConfig["KeyVaultName"];//readvaluefromconfigurationvarsecretClient=newSecretClient(newUri($"https://{keyVaultName}.vault.azure.net/"),newDefaultAzureCredential());config.AddAzureKeyVault(secretClient,newKeyVaultSecretManager());//addanextraconfigurationsource//Theframeworkcallsconfig.Build()AGAINtobuildthefinalIConfigurationRoot}})

 

  设备 Azure Key Vault 供给者必要一个设备值,以是你堕入了一个鸡和蛋的题目--正在你创修设备以前,你无奈增加设备源。

  管理举措是:

   增加初始设备值; 经由过程移用 IConfigurationBuilder.Build() 构修片面设备了局; 从天生的 IConfigurationRoot 中检索所需的设备值; 利用这些值来增加残剩的设备源; 框架隐含地移用 IConfigurationBuilder.Build(),天生终极的 IConfigurationRoot 并将其用于终极的行使设备。

  这全体流程有点乱,但它自身并无甚么题目,那末弱点是甚么呢?

  弱点是咱们必需移用 Build() 两次:一次是只利用第一个源来构修 IConfigurationRoot,另一次是利用总共源来构修 IConfiguartionRoot,囊括 Azure Key Vault 源。

  正在默许的 ConfigurationBuilder 杀青中,移用 Build() 会遍历总共的源,加载供给者,并将这些通报给 ConfigurationRoot 的一个新实例。

  

publicIConfigurationRootBuild(){varproviders=newList<IConfigurationProvider>();foreach(IConfigurationSourcesourceinSources){IConfigurationProviderprovider=source.Build(this);providers.Add(provider);}returnnewConfigurationRoot(providers);}

 

  而后,ConfigurationRoot 按序轮回遍历这些供给者,并加载设备值。

  

publicclassConfigurationRoot:IConfigurationRoot,IDisposable{privatereadonlyIList<IConfigurationProvider>_providers;privatereadonlyIList<IDisposable>_changeTokenRegistrations;publicConfigurationRoot(IList<IConfigurationProvider>providers){_providers=providers;_changeTokenRegistrations=newList<IDisposable>(providers.Count);foreach(IConfigurationProviderpinproviders){p.Load();_changeTokenRegistrations.Add(ChangeToken.OnChange(()=>p.GetReloadToken(),()=>RaiseChanged()));}}//...remainderofimplementation}

 

  倘若你正在行使启动时移用 Build() 两次,那末总共这些城市发作两次。

  个别来讲,从设备源获取数据一次以上并无大碍,但这是不用要的事情,况且通常触及到(绝对从容的)文献读取等。

  这是一种常睹的形式,以是正在 .NET 6 中引入了一个新的范例来防止这类从头构修,即 ConfigurationManager。

   4..NET 6 中的设备打点器

  举动 .NET 6 中简化行使模子的一片面,.NET 团队扩大了一个新的设备范例--ConfigurationManager。这品种型同时杀青了 IConfigurationBuilder 和 IConfigurationRoot。经由过程将这两种杀青团结正在一个简单的范例中,.NET 6 能够优化上一节中闪现的常睹形式。

  有了 ConfigurationManager,当 IConfigurationSource 被增加时(比方当你移用 AddJsonFile() 时),供给者被顷刻加载,设备被更新。这能够防止正在片面构修的景况下不能不屡次加载设备源。

  因为 IConfigurationBuilder 接口将源举动 IList 公然,是以杀青这一点比听起来要难少少:

  

publicinterfaceIConfigurationBuilder{IList<IConfigurationSource>Sources{get;}//..othermembers}

 

  从 ConfigurationManager 的角度来看,这个题目是 IList<> 揭示了 Add() 和 Remove() 函数。倘若利用一个纯粹的 List<>,花费者能够正在 ConfigurationManager 不领略的景况下增加和删除设备供给者。

  为明晰决这个题目,ConfigurationManager 利用一个自界说的 IList<> 杀青。这包罗对 ConfigurationManager 实例的援用,如许任何转变都能够反应正在设备中:

  

privateclassConfigurationSources:IList<IConfigurationSource>{privatereadonlyList<IConfigurationSource>_sources=new();privatereadonlyConfigurationManager_config;publicConfigurationSources(ConfigurationManagerconfig){_config=config;}publicvoidAdd(IConfigurationSourcesource){_sources.Add(source);_config.AddSource(source);//addthesourcetotheConfigurationManager}publicboolRemove(IConfigurationSourcesource){varremoved=_sources.Remove(source);_config.ReloadSources();//resetsourcesintheConfigurationManagerreturnremoved;}//...additionalimplementation}

 

  经由过程利用一个自界说的 IList<> 杀青,ConfigurationManager 确保每当有新的源被增加时就移用 AddSource()。这即是 ConfigurationManager 的上风所正在:移用 AddSource() 能够顷刻加载源:

  

ublicclassConfigurationManager{privatevoidAddSource(IConfigurationSourcesource){lock(_providerLock){IConfigurationProviderprovider=source.Build(this);_providers.Add(provider);provider.Load();_changeTokenRegistrations.Add(ChangeToken.OnChange(()=>provider.GetReloadToken(),()=>RaiseChanged()));}RaiseChanged();}}

 

  这个法子顷刻正在 IConfigurationSource 上移用 Build 来创修 IConfigurationProvider,并将其增加到供给者列外中。

  接上去,该法子移用 IConfigurationProvider.Load()。这将把数据加载到供给者中,(比方从情况变量、JSON 文献或 Azure Key Vault),这是高贵的方法,而这全体即是为了加载数据 正在畸形景况下,你只要向 IConfigurationBuilder 增加源,并能够必要屡次构修它,这就给出了最佳法子——源被加载一次,且唯有一次。

  ConfigurationManager 中 Build() 的杀青现正在甚么都没做,只是前往它本身:

  

IConfigurationRootIConfigurationBuilder.Build()=>this;

 

  固然,软件开垦是所相合于量度的题目。倘若你只增加源,那末正在增加源的时刻递增构修源就很无效。但是,倘若你移用任何其余 IList<> 函数,如 Clear()、Remove() 或索引器,ConfigurationManager 就必需移用 ReloadSources():

  

privatevoidReloadSources(){lock(_providerLock){DisposeRegistrationsAndProvidersUnsynchronized();_changeTokenRegistrations.Clear();_providers.Clear();foreach(varsourcein_sources){_providers.Add(source.Build(this));}foreach(varpin_providers){p.Load();_changeTokenRegistrations.Add(ChangeToken.OnChange(()=>p.GetReloadToken(),()=>RaiseChanged()));}}RaiseChanged();}

 

  正如你所看到的,倘若任何一个源蜕化了,ConfigurationManager 必需删除总共的货色并从头首先,迭代每一个源,从头加载它们。倘若你要对设备源举办大批的操纵,这很疾就会变得很高贵,况且会全部否认 ConfigurationManager 的原始上风。

  固然,删除源黑白常罕睹的,以是 ConfigurationManager 是为最常睹的景况而优化的。谁能猜到呢?

  下外给出了利用 ConfigurationBuilder 和 ConfigurationManager 的种种操纵的绝对本钱的终极总结:

  

   5.能否需属意 ConfigurationManager

  那末读了这么众,你能否该当属意你是利用 ConfigurationManager 如故 ConfigurationBuilder?

  大概不应当。

  正在 .NET 6 中引入的新的 WebApplicationBuilder 利用 ConfigurationManager,它优化了我下面描写的利用景况,即你必要片面构修你的设备。

  但是,ASP.NET Core 初期版本中引入的 WebHostBuilder 或 HostBuilder 正在 .NET 6 中如故尽头受维持,它们继承正在幕后利用 ConfigurationBuilder 和 ConfigurationRoot 范例。

  我以为独一必要谨慎的景况是,倘若你正在某个处所依附 IConfigurationBuilder 或 IConfigurationRoot 举动详细范例的 ConfigurationBuilder 或 ConfigurationRoot。这正在我看来黑白常不太能够发作的,倘若你依附这一点,我很念领略缘由。

  但除了这个小众的各异,老范例不会消灭,以是没有须要顾虑。倘若你必要举办片面构修,而且你利用了新的 WebApplicationBuilder,那末你的行使次第将会有更高的职能,这一点你该当感触安乐。

   6.总结

  正在这篇著作中,我描写了正在 .NET 6 中引入的新的 ConfigurationManager 范例,并正在最小(Minimal) API 示例中被新的 WebApplicationBuilder 所利用。引入 ConfigurationManager 是为了优化一种常睹的景况,即你必要片面构树立备。这往往是由于设备供给者自身必要少少设备,比方,从 Azure Key Vault 加载 secrects,必要设备解释要利用哪一个 Vault 库。

  ConfigurationManager 优化了这类景况:它正在增加源时顷刻加载,而不是比及你移用 Build()。这就防止了正在片面构修景况下重修设备的必要,其价钱是其余不常睹操纵(如删除一个源)能够变得更高贵的。

文章推荐:

2022 年中国人工智能行业发展现状与市场规模分析 市场规模超 3000 亿元

该来的总要来! 切尔西老板将彻底退出英国市场

雷神黑武士四代开售:i7搭RTX3060不到9千元

智慧城市中 5G 和物联网的未来