Configuration 实现了两个接口 IConfiguration 和 IConfigurationSourceContainer
前文中 IConfigurationSourceContainer 的扩展方法 也就等同于Configuration的扩展方法。
最最重要的方法:
private readonly IList<IConfigurationSource> _sources = new List<IConfigurationSource>(); private readonly IList<ICommitableConfigurationSource> _committableSources = new List<ICommitableConfigurationSource>();
public IConfigurationSourceContainer Add(IConfigurationSource configurationSource)
{
configurationSource.Load();
return AddLoadedSource(configurationSource);
}
internal IConfigurationSourceContainer AddLoadedSource(IConfigurationSource configurationSource)
{
_sources.Add(configurationSource);
if (configurationSource is ICommitableConfigurationSource)
{
_committableSources.Add(configurationSource as ICommitableConfigurationSource);
}
return this;
}
实现IConfigurationSource 的有前文中的 IniFile;Json;Xml;CommandLine;EnvironmentVariables;另外还有一个 MemoryConfigurationSource;
如果添加了多个 且具有相同的Key; 如何取值呢? 答案是最后添加的。 代码如下:
public bool TryGet(string key, out string value)
{
if (key == null) throw new ArgumentNullException("key");
// If a key in the newly added configuration source is identical to a key in a
// formerly added configuration source, the new one overrides the former one.
// So we search in reverse order, starting with latest configuration source.
foreach (var src in _sources.Reverse())
{
if (src.TryGet(key, out value))
{
return true;
}
}
value = null;
return false;
}
赋值则是每一个都进行赋值:代码如下:
public void Set(string key, string value)
{
if (key == null) throw new ArgumentNullException("key");
if (value == null) throw new ArgumentNullException("value");
foreach (var src in _sources)
{
src.Set(key, value);
}
}
Reload 是每一个都加载:
public void Reload()
{
foreach (var src in _sources)
{
src.Load();
}
}
提交保存则是只保存最后一个可以保存的ConfigurationSource 可以保存的有 IniFile Json Xml;
public void Commit()
{
var final = _committableSources.LastOrDefault();
if (final == null)
{
throw new InvalidOperationException(Resources.Error_NoCommitableSource);
}
final.Commit();
}
GetSubKey 则通过前缀 创建 实现IConfiguration的 ConfigurationFocus 代码如下:
public IConfiguration GetSubKey(string key)
{
return new ConfigurationFocus(this, key + Constants.KeyDelimiter);
}
{"Data:DB1:Connection1", "MemVal1"} 调用 GetSubKey("Data") 则变成 {DB1:Connection1", "MemVal1"}
理解一下下面的代码:
public IEnumerable<KeyValuePair<string, IConfiguration>> GetSubKeys(string key)
{
if (key == null) throw new ArgumentNullException("key");
return GetSubKeysImplementation(key + Constants.KeyDelimiter);
}
private IEnumerable<KeyValuePair<string, IConfiguration>> GetSubKeysImplementation(string prefix)
{
var segments = _sources.Aggregate(
Enumerable.Empty<string>(),
(seed, source) => source.ProduceSubKeys(seed, prefix, Constants.KeyDelimiter));
var distinctSegments = segments.Distinct();
return distinctSegments.Select(segment => CreateConfigurationFocus(prefix, segment));
}
private KeyValuePair<string, IConfiguration> CreateConfigurationFocus(string prefix, string segment)
{
return new KeyValuePair<string, IConfiguration>(
segment,
new ConfigurationFocus(this, prefix + segment + Constants.KeyDelimiter));
}
看一下单元测试代码(下方代码):
segments 包含 三个值:”DB2Connection“,"DB1",”DB1“
distinctSegments 只有 ”DB2Connection“,"DB1"
结果如下:
"DB2Connection"------------new ConfigurationFocus(this, "Data:"+ "DB2Connection:");
"DB1" ------------new ConfigurationFocus(this, "Data:"+ "DB1:");
public void CanGetSubKeys()
{
// Arrange
var dic1 = new Dictionary<string, string>()
{
{"Data:DB1:Connection1", "MemVal1"},
{"Data:DB1:Connection2", "MemVal2"}
};
var dic2 = new Dictionary<string, string>()
{
{"Data:DB2Connection", "MemVal3"}
};
var dic3 = new Dictionary<string, string>()
{
{"DataSource:DB3:Connection", "MemVal4"}
};
var memConfigSrc1 = new MemoryConfigurationSource(dic1);
var memConfigSrc2 = new MemoryConfigurationSource(dic2);
var memConfigSrc3 = new MemoryConfigurationSource(dic3);
var config = new Configuration();
config.AddLoadedSource(memConfigSrc1);
config.AddLoadedSource(memConfigSrc2);
config.AddLoadedSource(memConfigSrc3);
// Act
var configFocusList = config.GetSubKeys("Data");
var subKeysSet = configFocusList.ToDictionary(e => e.Key, e => e.Value);
// Assert
Assert.Equal(2, configFocusList.Count());
Assert.Equal("MemVal1", subKeysSet["DB1"].Get("Connection1"));
Assert.Equal("MemVal2", subKeysSet["DB1"].Get("Connection2"));
Assert.Equal("MemVal3", subKeysSet["DB2Connection"].Get(null));
Assert.False(subKeysSet.ContainsKey("DB3"));
Assert.False(subKeysSet.ContainsKey("Source:DB3"));
}
浙公网安备 33010602011771号