| File: System\Configuration\RuntimeConfigurationRecord.cs | Web Access |
| Project: src\runtime\src\libraries\System.Configuration.ConfigurationManager\src\System.Configuration.ConfigurationManager.csproj (System.Configuration.ConfigurationManager) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Configuration.Internal; using System.Reflection; using System.Xml; namespace System.Configuration { internal sealed class RuntimeConfigurationRecord : BaseConfigurationRecord { private static readonly SimpleBitVector32 s_runtimeClassFlags = new SimpleBitVector32( ClassSupportsChangeNotifications | ClassSupportsRefresh | ClassSupportsImpersonation | ClassSupportsRestrictedPermissions | ClassSupportsDelayedInit); private RuntimeConfigurationRecord() { } protected override SimpleBitVector32 ClassFlags => s_runtimeClassFlags; internal static IInternalConfigRecord Create( InternalConfigRoot configRoot, IInternalConfigRecord parent, string configPath) { RuntimeConfigurationRecord configRecord = new RuntimeConfigurationRecord(); configRecord.Init(configRoot, (BaseConfigurationRecord)parent, configPath, null); return configRecord; } // Create the factory that will evaluate configuration protected override object CreateSectionFactory(FactoryRecord factoryRecord) { return new RuntimeConfigurationFactory(this, factoryRecord); } // parentConfig contains the config that we'd merge with. protected override object CreateSection(bool inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader) { // Get the factory used to create a section. RuntimeConfigurationFactory factory = (RuntimeConfigurationFactory)factoryRecord.Factory; // Use the factory to create a section. object config = factory.CreateSection(this, factoryRecord, sectionRecord, parentConfig, reader); return config; } protected override object UseParentResult(string configKey, object parentResult, SectionRecord sectionRecord) { return parentResult; } protected override object GetRuntimeObject(object result) { object runtimeObject; ConfigurationSection section = result as ConfigurationSection; if (section == null) runtimeObject = result; else { // Call into config section while impersonating process or UNC identity // so that the section could read files from disk if needed try { runtimeObject = section.GetRuntimeObject(); } catch (Exception e) { throw new ConfigurationErrorsException( SR.Format(SR.Config_exception_in_config_section_handler, section.SectionInformation.SectionName), e); } } return runtimeObject; } private sealed class RuntimeConfigurationFactory { private ConstructorInfo _sectionCtor; private IConfigurationSectionHandler _sectionHandler; internal RuntimeConfigurationFactory(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord) { Init(configRecord, factoryRecord); } private void Init(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord) { // Get the type of the factory Type type = TypeUtil.GetType(configRecord.Host, factoryRecord.FactoryTypeName, true); // If the type is a ConfigurationSection, that's the type. if (typeof(ConfigurationSection).IsAssignableFrom(type)) { _sectionCtor = TypeUtil.GetConstructor(type, typeof(ConfigurationSection), true); } else { // Note: in v1, IConfigurationSectionHandler is in effect a factory that has a Create method // that creates the real section object. // throws if type does not implement IConfigurationSectionHandler TypeUtil.VerifyAssignableType(typeof(IConfigurationSectionHandler), type, true); // Create an instance of the handler _sectionHandler = (IConfigurationSectionHandler)TypeUtil.CreateInstance(type); } } // Throw an exception if an attribute within a legacy section is one of our // reserved locking attributes. We do not want admins to think they can lock // an attribute or element within a legacy section. private static void CheckForLockAttributes(string sectionName, XmlNode xmlNode) { XmlAttributeCollection attributes = xmlNode.Attributes; if (attributes != null) { foreach (XmlAttribute attribute in attributes) if (ConfigurationElement.IsLockAttributeName(attribute.Name)) { throw new ConfigurationErrorsException( SR.Format(SR.Config_element_locking_not_supported, sectionName), attribute); } } foreach (XmlNode child in xmlNode.ChildNodes) if (xmlNode.NodeType == XmlNodeType.Element) CheckForLockAttributes(sectionName, child); } internal object CreateSection(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader) { object config; if (_sectionCtor != null) { ConfigurationSection configSection = (ConfigurationSection)_sectionCtor.Invoke(null); configSection.SectionInformation.SetRuntimeConfigurationInformation(configRecord, factoryRecord, sectionRecord); configSection.CallInit(); ConfigurationSection parentSection = (ConfigurationSection)parentConfig; configSection.Reset(parentSection); if (reader != null) configSection.DeserializeSection(reader); // throw if there are any cached errors ConfigurationErrorsException errors = configSection.GetErrors(); if (errors != null) throw errors; // don't allow changes to sections at runtime configSection.SetReadOnly(); // reset the modified bit configSection.ResetModified(); config = configSection; } else { if (reader != null) { XmlNode xmlNode = ErrorInfoXmlDocument.CreateSectionXmlNode(reader); CheckForLockAttributes(factoryRecord.ConfigKey, xmlNode); // In v1, our old section handler expects a context that contains the virtualPath from the configPath object configContext = configRecord.Host.CreateDeprecatedConfigContext(configRecord.ConfigPath); config = _sectionHandler.Create(parentConfig, configContext, xmlNode); } else config = null; } return config; } } } }