- 发布日期:2023-10-30 02:53 点击次数:60
在这个系列中,我将探索一下 .NET 6 中的一些新特色。依然有好多对于 .NET 6 的本色,包括好多来自 .NET 和 ASP.NET 团队本人的著述。在这个系列中,我将探索一下这些特色背后的一些代码。
在这第一篇著述中,来相干一下 ConfigurationManager 类,讲一下为什么要新增这个类,并看一下它的的一些竣工代码。
皇冠体育hg86a
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 列表中。
public 欧博龙虎斗interface IConfigurationBuilder { IDictionary<string, object> Properties { get; } IList<IConfigurationSource> Sources { get; } IConfigurationBuilder Add(IConfigurationSource source); IConfigurationRoot Build(); }
同期,IConfigurationRoot 代表最终“层”的树立值,聚合了每个树立源的总共值,以提供总共树立值的最终“平面”视图。
后者树立提供者(环境变量)遮掩了前者树立提供者(appsettings.json、sharedsettings.json)添加的值。
在 .NET 5 及往常的版块中,IConfigurationBuilder 和 IConfigurationRoot 接口永别由 ConfigurationBuilder 和 ConfigurationRoot 竣工。如果你径直使用这些类型,你可能会这样作念:
var builder = new ConfigurationBuilder(); // add static values builder.AddInMemoryCollection(new Dictionary<string, string> { { "MyKey", "MyValue" }, }); // add values from a json file builder.AddJsonFile("appsettings.json"); // create the IConfigurationRoot instance IConfigurationRoot config = builder.Build(); string value = config["MyKey"]; // get a value IConfigurationSection section = config.GetSection("SubSection"); //get a section
在一个典型的 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" configuration etc config.AddJsonFile("appsettings.json"); config.AddEnvironmentVariables(); if (context.HostingEnvironment.IsProduction()) { IConfigurationRoot partialConfig = config.Build(); // build partial config string keyVaultName = partialConfig["KeyVaultName"]; // read value from configuration var secretClient = new SecretClient( new Uri($"https://{keyVaultName}.vault.azure.net/"), new DefaultAzureCredential()); config.AddAzureKeyVault(secretClient, new KeyVaultSecretManager()); // add an extra configuration source // The framework calls config.Build() AGAIN to build the final IConfigurationRoot } })
树立 Azure Key Vault 提供者需要一个树立值,是以你堕入了一个鸡和蛋的问题--在你修复树立之前,你无法添加树立源。
网络视频显示,两名少年坐在海滩上,一人将头埋在两腿之间,几名救援队队员围在他们身边,一名民警对两名少年说着什么。不远处的海面上,几艘快艇和摩托艇正在展开搜索,数名医护人员已经赶到现场。
皇冠体彩下载安装责罚成见是:
北京赛车轮盘 添加“驱动”树立值; 通过调用 IConfigurationBuilder.Build() 构建“部分”树立效果; 从生成的 IConfigurationRoot 中检索所需的树立值; 使用这些值来添加剩余的树立源; 框架隐含地调用 IConfigurationBuilder.Build(),生成最终的 IConfigurationRoot 并将其用于最终的运用树立。这总共这个词历程有点乱,但它本人并莫得什么问题,那么污点是什么呢?
博彩平台推广污点是咱们必须调用 Build() 两次:一次是只使用第一个源来构建 IConfigurationRoot,另一次是使用总共源来构建 IConfiguartionRoot,包括 Azure Key Vault 源。
在默许的 ConfigurationBuilder 竣工中,调用 Build() 会遍历总共的源,加载提供者,并将这些传递给 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())); } } // ... remainder of implementation }
如果你在运用启动时调用 Build() 两次,那么总共这些王人会发生两次。
一般来说,从树立源得回数据一次以上并无大碍,但这是不必要的使命,而且粗造触及到(相对迟缓的)文献读取等。
这是一种常见的形式,是以在 .NET 6 中引入了一个新的类型来幸免这种“再行构建”,即 ConfigurationManager。
4..NET 6 中的树立管束器当作 .NET 6 中“简化”运用模子的一部分,皇冠投注网.NET 团队增多了一个新的树立类型--ConfigurationManager。这种类型同期竣工了 IConfigurationBuilder 和 IConfigurationRoot。通过将这两种竣工聚合在一个单一的类型中,.NET 6 不错优化上一节中展示的常见形式。
胜率有了 ConfigurationManager,当 IConfigurationSource 被添加时(举例当你调用 AddJsonFile() 时),提供者被立即加载,树立被更新。这不错幸免在部分构建的情况下不得未几次加载树立源。
由于 IConfigurationBuilder 接口将源当作 IList 公开,因此竣工这小数比听起来要难一些:
public interface IConfigurationBuilder { IList<IConfigurationSource> Sources { get; } // .. other members }
从 ConfigurationManager 的角度来看,这个问题是 IList<> 披露了 Add() 和 Remove() 函数。如果使用一个简便的 List<>,破钞者不错在 ConfigurationManager 不知谈的情况下添加和删除树立提供者。
为了责罚这个问题,ConfigurationManager 使用一个自界说的 IList<> 竣工。这包含对 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); // add the source to the ConfigurationManager } public bool Remove(IConfigurationSource source) { var removed = _sources.Remove(source); _config.ReloadSources(); // reset sources in the ConfigurationManager return removed; } // ... additional implementation }
通过使用一个自界说的 IList<> 竣工,ConfigurationManager 确保每当有新的源被添加时就调用 AddSource()。这等于 ConfigurationManager 的上风所在:调用 AddSource() 不错立即加载源:
ublic 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()。这将把数据加载到提供者中,(举例从环境变量、JSON 文献或 Azure Key Vault),这是“不菲”的时事,而这一切等于为了加载数据 在“平淡”情况下,你只需向 IConfigurationBuilder 添加源,并可能需要屡次构建它,这就给出了“最好”行动——源被加载一次,且唯惟一次。
ConfigurationManager 中 Build() 的竣工目下什么王人没作念,仅仅复返它我方:
IConfigurationRoot IConfigurationBuilder.Build() => this;
固然,软件开采是所相对于量度的问题。如果你只添加源,那么在添加源的时分递加构建源就很有用。但是,如果你调用任何其他 IList<> 函数,如 Clear()、Remove() 或索引器,ConfigurationManager 就必须调用 ReloadSources():
最近,一项有关运动员的研究显示,高强度训练会对运动员的身体健康造成一定的影响,引起了全球运动爱好者和体育科学家的关注和讨论。如何正确地进行运动训练和保护身体健康已经成为了全球运动爱好者和科学家们共同关注的话题。想要了解更多关于如何正确地进行运动训练和保护身体健康的热门话题和新闻,不妨加入皇冠体育博彩平台,与全球运动爱好者和科学家们一起分享和探讨。皇冠赌博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(); }
正如你所看到的,如果任何一个源转换了,ConfigurationManager 必须删除总共的东西并再行脱手,迭代每个源,再行加载它们。如果你要对树立源进行无数的操作,这很快就会变得很不菲,而且会完满申辩 ConfigurationManager 的原始上风。
固然,删除源是终点凄惨的,是以 ConfigurationManager 是为最常见的情况而优化的。谁能猜到呢?
下表给出了使用 ConfigurationBuilder 和 ConfigurationManager 的各式操作的相对本钱的最终追思:
那么读了这样多,你是否应该关切你是使用 ConfigurationManager 如故 ConfigurationBuilder?
也许不应该。
zh皇冠体育 维基百科在 .NET 6 中引入的新的 WebApplicationBuilder 使用 ConfigurationManager,它优化了我上头形容的使用情况,即你需要“部分构建”你的树立。
但是,ASP.NET Core 早期版块中引入的 WebHostBuilder 或 HostBuilder 在 .NET 6 中仍然终点受救援,它们不时在幕后使用 ConfigurationBuilder 和 ConfigurationRoot 类型。
博彩平台优惠我以为唯一需要贵重的情况是,如果你在某个地点依赖 IConfigurationBuilder 或 IConfigurationRoot 当作具体类型的 ConfigurationBuilder 或 ConfigurationRoot。这在我看来是终点不太可能发生的,如果你依赖这小数,我很念念知谈原因。
皇冠客服飞机:@seo3687但除了这个小众的例外,“老”类型不会隐没,是以莫得必要顾虑。如果你需要进行“部分构建”,况兼你使用了新的 WebApplicationBuilder,那么你的运用轨范将会有更高的性能,这小数你应该感到欢笑。
6.追思在这篇著述中,我形容了在 .NET 6 中引入的新的 ConfigurationManager 类型,并在最小(Minimal) API 示例中被新的 WebApplicationBuilder 所使用。引入 ConfigurationManager 是为了优化一种常见的情况,即你需要“部分构建”树立。这粗造是因为树立提供者本人需要一些树立,举例,从 Azure Key Vault 加载 secrects,需要树立标明要使用哪个 Vault 库。
ConfigurationManager 优化了这种情况:它在添加源时立即加载,而不是比及你调用 Build()。这就幸免了在“部分构建”情况下“重建”树立的需要,其代价是其他不常见操作(如删除一个源)可能变得更不菲的。