<PackageReference Include="System.Configuration.ConfigurationManager" Version="8.0.0" />

InternalConfigRoot

using System.Threading; namespace System.Configuration.Internal { internal sealed class InternalConfigRoot : IInternalConfigRoot { private ReaderWriterLock _hierarchyLock; private bool _isDesignTime; internal IInternalConfigHost Host { get; set; } internal UpdateConfigHost UpdateConfigHost { get; set; } internal BaseConfigurationRecord RootConfigRecord { get; set; } internal Configuration CurrentConfiguration { get; } bool IInternalConfigRoot.IsDesignTime { get { return _isDesignTime; } } public event InternalConfigEventHandler ConfigChanged; public event InternalConfigEventHandler ConfigRemoved; internal InternalConfigRoot() { } internal InternalConfigRoot(Configuration currentConfiguration, UpdateConfigHost host) { CurrentConfiguration = currentConfiguration; UpdateConfigHost = host; } void IInternalConfigRoot.Init(IInternalConfigHost host, bool isDesignTime) { Host = host; _isDesignTime = isDesignTime; _hierarchyLock = new ReaderWriterLock(); if (_isDesignTime) RootConfigRecord = MgmtConfigurationRecord.Create(this, null, string.Empty, null); else RootConfigRecord = (BaseConfigurationRecord)RuntimeConfigurationRecord.Create(this, null, string.Empty); } public object GetSection(string section, string configPath) { BaseConfigurationRecord baseConfigurationRecord = (BaseConfigurationRecord)GetUniqueConfigRecord(configPath); return baseConfigurationRecord.GetSection(section); } public string GetUniqueConfigPath(string configPath) { return GetUniqueConfigRecord(configPath)?.ConfigPath; } public IInternalConfigRecord GetUniqueConfigRecord(string configPath) { BaseConfigurationRecord baseConfigurationRecord = (BaseConfigurationRecord)GetConfigRecord(configPath); while (baseConfigurationRecord.IsEmpty) { BaseConfigurationRecord parent = baseConfigurationRecord.Parent; if (parent.IsRootConfig) break; baseConfigurationRecord = parent; } return baseConfigurationRecord; } public IInternalConfigRecord GetConfigRecord(string configPath) { if (ConfigPathUtility.IsValid(configPath)) { string[] parts = ConfigPathUtility.GetParts(configPath); try { AcquireHierarchyLockForRead(); HlFindConfigRecord(parts, out int nextIndex, out BaseConfigurationRecord currentRecord); if (nextIndex == parts.Length || !currentRecord.HlNeedsChildFor(parts[nextIndex])) return currentRecord; } finally { ReleaseHierarchyLockForRead(); } try { AcquireHierarchyLockForWrite(); HlFindConfigRecord(parts, out int nextIndex2, out BaseConfigurationRecord currentRecord2); if (nextIndex2 != parts.Length) { string text = string.Join("/", parts, 0, nextIndex2); while (nextIndex2 < parts.Length && currentRecord2.HlNeedsChildFor(parts[nextIndex2])) { string text2 = parts[nextIndex2]; text = ConfigPathUtility.Combine(text, text2); BaseConfigurationRecord baseConfigurationRecord = _isDesignTime ? MgmtConfigurationRecord.Create(this, currentRecord2, text, null) : ((BaseConfigurationRecord)RuntimeConfigurationRecord.Create(this, currentRecord2, text)); currentRecord2.HlAddChild(text2, baseConfigurationRecord); nextIndex2++; currentRecord2 = baseConfigurationRecord; } return currentRecord2; } return currentRecord2; } finally { ReleaseHierarchyLockForWrite(); } } throw ExceptionUtil.ParameterInvalid("configPath"); } public void RemoveConfig(string configPath) { RemoveConfigImpl(configPath, null); } private void AcquireHierarchyLockForRead() { if (_hierarchyLock.IsReaderLockHeld) throw ExceptionUtil.UnexpectedError("System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForRead - reader lock already held by this thread"); if (_hierarchyLock.IsWriterLockHeld) throw ExceptionUtil.UnexpectedError("System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForRead - writer lock already held by this thread"); _hierarchyLock.AcquireReaderLock(-1); } private void ReleaseHierarchyLockForRead() { if (_hierarchyLock.IsReaderLockHeld) _hierarchyLock.ReleaseReaderLock(); } private void AcquireHierarchyLockForWrite() { if (_hierarchyLock.IsReaderLockHeld) throw ExceptionUtil.UnexpectedError("System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForWrite - reader lock already held by this thread"); if (_hierarchyLock.IsWriterLockHeld) throw ExceptionUtil.UnexpectedError("System.Configuration.Internal.InternalConfigRoot::AcquireHierarchyLockForWrite - writer lock already held by this thread"); _hierarchyLock.AcquireWriterLock(-1); } private void ReleaseHierarchyLockForWrite() { if (_hierarchyLock.IsWriterLockHeld) _hierarchyLock.ReleaseWriterLock(); } private void HlFindConfigRecord(string[] parts, out int nextIndex, out BaseConfigurationRecord currentRecord) { currentRecord = RootConfigRecord; for (nextIndex = 0; nextIndex < parts.Length; nextIndex++) { BaseConfigurationRecord baseConfigurationRecord = currentRecord.HlGetChild(parts[nextIndex]); if (baseConfigurationRecord == null) break; currentRecord = baseConfigurationRecord; } } private void RemoveConfigImpl(string configPath, BaseConfigurationRecord configRecord) { if (!ConfigPathUtility.IsValid(configPath)) throw ExceptionUtil.ParameterInvalid("configPath"); string[] parts = ConfigPathUtility.GetParts(configPath); BaseConfigurationRecord currentRecord; try { AcquireHierarchyLockForWrite(); HlFindConfigRecord(parts, out int nextIndex, out currentRecord); if (nextIndex != parts.Length || (configRecord != null && configRecord != currentRecord)) return; currentRecord.Parent.HlRemoveChild(parts[parts.Length - 1]); } finally { ReleaseHierarchyLockForWrite(); } OnConfigRemoved(new InternalConfigEventArgs(configPath)); currentRecord.CloseRecursive(); } public void RemoveConfigRecord(BaseConfigurationRecord configRecord) { RemoveConfigImpl(configRecord.ConfigPath, configRecord); } public void ClearResult(BaseConfigurationRecord configRecord, string configKey, bool forceEvaluation) { string[] parts = ConfigPathUtility.GetParts(configRecord.ConfigPath); try { AcquireHierarchyLockForRead(); HlFindConfigRecord(parts, out int nextIndex, out BaseConfigurationRecord currentRecord); if (nextIndex == parts.Length && configRecord == currentRecord) currentRecord.HlClearResultRecursive(configKey, forceEvaluation); } finally { ReleaseHierarchyLockForRead(); } } private void OnConfigRemoved(InternalConfigEventArgs e) { this.ConfigRemoved?.Invoke(this, e); } internal void FireConfigChanged(string configPath) { OnConfigChanged(new InternalConfigEventArgs(configPath)); } private void OnConfigChanged(InternalConfigEventArgs e) { this.ConfigChanged?.Invoke(this, e); } } }