.NET 6 中的 ConfigurationManager
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.NET 6 中的 ConfigurationManager相关的知识,希望对你有一定的参考价值。
.NET 6 中的 ConfigurationManager
Intro
.NET 6 为了 Minimal API 引入了一些新东西,其中就包含了一个全新的配置对象 ConfigurationManager
这并不是 .NET Framework 里的静态类 ConfigurationManager
,而是 .NET Core 里的配置 Microsoft.Extensions.Configuration
中的一个新类型,新的 ConfigurationManager
对象是之前的 ConfigurationBuilder
和 ConfigurationRoot
的结合
Implement
API Proposal:
namespace Microsoft.Extensions.Configuration
{
+ public sealed class ConfigurationManager : IConfigurationRoot, IConfigurationBuilder, IDisposable
+ {
+ public ConfigurationManager();
+ public string? this[string key] { get; set; }
+ public IConfigurationSection GetSection(string key);
+ public void Dispose();
+ }
Implement:
public sealed class ConfigurationManager : IConfigurationBuilder, IConfigurationRoot, IDisposable
{
private readonly ConfigurationSources _sources;
private readonly ConfigurationBuilderProperties _properties;
private readonly object _providerLock = new();
private readonly List<IConfigurationProvider> _providers = new();
private readonly List<IDisposable> _changeTokenRegistrations = new();
private ConfigurationReloadToken _changeToken = new();
/// <summary>
/// Creates an empty mutable configuration object that is both an <see cref="IConfigurationBuilder"/> and an <see cref="IConfigurationRoot"/>.
/// </summary>
public ConfigurationManager()
{
_sources = new ConfigurationSources(this);
_properties = new ConfigurationBuilderProperties(this);
// Make sure there's some default storage since there are no default providers.
this.AddInMemoryCollection();
AddSource(_sources[0]);
}
// ...
}
ConfigurationManager
在添加 ConfigurationSource
的时候也会注册 IConfigurationProvider
,这样在添加 Source 之后就能够拿到 Configuration 中的配置了,在实现上,微软封装了一个私有的 ConfigurationSource
的类型,这里我们看一下注册配置源的代码
private class ConfigurationSources : IList<IConfigurationSource>
{
private readonly List<IConfigurationSource> _sources = new();
private readonly ConfigurationManager _config;
public ConfigurationSources(ConfigurationManager config)
{
_config = config;
}
public IConfigurationSource this[int index]
{
get => _sources[index];
set
{
_sources[index] = value;
_config.ReloadSources();
}
}
public void Add(IConfigurationSource source)
{
_sources.Add(source);
_config.AddSource(source);
}
// ...
}
ConfigurationManager
中的 AddSource
方法实现如下:
IConfigurationBuilder IConfigurationBuilder.Add(IConfigurationSource source)
{
_sources.Add(source ?? throw new ArgumentNullException(nameof(source)));
return this;
}
private void RaiseChanged()
{
var previousToken = Interlocked.Exchange(ref _changeToken, new ConfigurationReloadToken());
previousToken.OnReload();
}
// Don't rebuild and reload all providers in the common case when a source is simply added to the IList.
private void AddSource(IConfigurationSource source)
{
lock (_providerLock)
{
var provider = source.Build(this);
_providers.Add(provider);
provider.Load();
_changeTokenRegistrations.Add(ChangeToken.OnChange(() => provider.GetReloadToken(), () => RaiseChanged()));
}
RaiseChanged();
}
可以看到每次新加一个配置源的时候,都会去构建对应的一个 IConfigurationProvider
而且会去加载配置数据并注册配置更新事件,所以我们注册完配置之后才能够获取到配置,更多实现细节参考 Github 上的源码:https://github.com/dotnet/runtime/blob/v6.0.0-rc.1.21451.13/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs
Sample
来看下面使用时的 Sample 吧,非常的简单
const string testKey = "test";
var configuration = new ConfigurationManager();
Console.WriteLine(configuration[testKey]);
configuration.AddInMemoryCollection(new Dictionary<string, string>()
{
{ testKey, "test" }
});
Console.WriteLine(configuration[testKey]);
Console.ReadLine();
输出结果如下:
第一次输出的时候还没有注册配置输出的是空,第一次输出的时候已经注册了配置输出的是我们配置的值
代码示例在可以从 Github 获取 https://github.com/WeihanLi/SamplesInPractice/blob/master/net6sample/ConfigurationManagerSample/Program.cs
More
目前来说,ConfigurationManager
对象主要是为了 .NET 6 的 Minimal API 的需要,.NET 6 的 Minimal API 里用了这个,可以参考:https://github.com/dotnet/aspnetcore/blob/v6.0.0-rc.1.21452.15/src/DefaultBuilder/src/WebApplicationBuilder.cs ,但就像上面的示例一样,我们也是可以直接使用的,而且原来的 IConfigurationBuilder
依然是可以用的,无需担心升级到 .NET 6 会 break 的问题。
对于需要用到配置的测试程序直接用 ConfigurationManager
会更为简单一些,不需要先声明一个 ConfigurationBuilder
的对象注册好配置之后再构建一个 IConfiguration
对象,直接用一个对象就可以了,至少从我们写代码的角度会简单很多,但是性能会稍差一些,注册的配置源越多越明显,因为 ConfigurationManager
每次注册配置源的时候都会去构建和注册 IConfigurationProvider
而 IConfigurationBuilder
则是在最后 Build
的时候才构建一次,不过通常我们的配置也只是启动时只用配置一次,个人认为是可以接受的
References
https://github.com/dotnet/runtime/blob/v6.0.0-rc.1.21451.13/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs
https://github.com/dotnet/runtime/blob/v6.0.0-rc.1.21451.13/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationRoot.cs
https://github.com/dotnet/runtime/blob/v6.0.0-rc.1.21451.13/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationBuilder.cs
https://github.com/dotnet/runtime/pull/55338
https://github.com/dotnet/runtime/issues/51770
https://github.com/dotnet/aspnetcore/blob/v6.0.0-rc.1.21452.15/src/DefaultBuilder/src/BootstrapHostBuilder.cs
https://github.com/dotnet/aspnetcore/blob/v6.0.0-rc.1.21452.15/src/DefaultBuilder/src/WebApplicationBuilder.cs
https://github.com/WeihanLi/SamplesInPractice/blob/master/net6sample/ConfigurationManagerSample/Program.cs
以上是关于.NET 6 中的 ConfigurationManager的主要内容,如果未能解决你的问题,请参考以下文章
inode 列 (proc/net/tcp(6)) 中的值是啥意思?
.NET 6 中的 ConfigurationManager