File: System\Diagnostics\SwitchElementsCollection.cs
Web Access
Project: src\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.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Xml;
 
namespace System.Diagnostics
{
    [ConfigurationCollection(typeof(SwitchElement))]
    internal sealed class SwitchElementsCollection : ConfigurationElementCollection
    {
        public new SwitchElement this[string name] => (SwitchElement)BaseGet(name);
        public override ConfigurationElementCollectionType CollectionType => ConfigurationElementCollectionType.AddRemoveClearMap;
        protected override ConfigurationElement CreateNewElement() => new SwitchElement();
        protected override object GetElementKey(ConfigurationElement element) => ((SwitchElement)element).Name;
    }
 
    internal sealed class SwitchElement : ConfigurationElement
    {
        private static readonly ConfigurationPropertyCollection _properties = new ConfigurationPropertyCollection();
        private static readonly ConfigurationProperty _propName = new("name", typeof(string), "", ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey);
        private static readonly ConfigurationProperty _propValue = new("value", typeof(string), null, ConfigurationPropertyOptions.IsRequired);
 
        private StringDictionary _attributes;
 
        static SwitchElement()
        {
            _properties.Add(_propName);
            _properties.Add(_propValue);
        }
 
        public StringDictionary Attributes => _attributes ??= new StringDictionary();
 
        [ConfigurationProperty("name", DefaultValue = "", IsRequired = true, IsKey = true)]
        public string Name => (string)this[_propName];
 
        protected internal override ConfigurationPropertyCollection Properties => _properties;
 
        [ConfigurationProperty("value", IsRequired = true)]
        public string Value => (string)this[_propValue];
 
        // Our optional attributes implementation is little convoluted as there is
        // no such first class mechanism from the config system. We basically cache
        // any "unrecognized" attribute here and serialize it out later.
        protected override bool OnDeserializeUnrecognizedAttribute(string name, string value)
        {
            Attributes.Add(name, value);
            return true;
        }
 
        // We need to serialize optional attributes here, a better place would have
        // been inside SerializeElement but the base class implementation from
        // ConfigurationElement doesn't take into account for derived class doing
        // extended serialization, it basically writes out child element that
        // forces the element closing syntax, so any attribute serialization needs
        // to happen before normal element serialization from ConfigurationElement.
        // This means we would write out custom attributes ahead of normal ones.
        // The other alternative would be to re-implement the entire routine here
        // which is an overkill and a maintenance issue.
        protected override void PreSerialize(XmlWriter writer)
        {
            if (_attributes != null)
            {
                IDictionaryEnumerator e = (IDictionaryEnumerator)_attributes.GetEnumerator();
                while (e.MoveNext())
                {
                    string xmlValue = (string)e.Value;
                    string xmlName = (string)e.Key;
 
                    if ((xmlValue != null) && (writer != null))
                    {
                        writer.WriteAttributeString(xmlName, xmlValue);
                    }
                }
            }
        }
 
        // Account for optional attributes from custom listeners.
        protected internal override bool SerializeElement(XmlWriter writer, bool serializeCollectionKey)
        {
            bool DataToWrite = base.SerializeElement(writer, serializeCollectionKey);
            DataToWrite = DataToWrite || ((_attributes != null) && (_attributes.Count > 0));
            return DataToWrite;
        }
 
        protected internal override void Unmerge(ConfigurationElement sourceElement,
                                                 ConfigurationElement parentElement,
                                                 ConfigurationSaveMode saveMode)
        {
            base.Unmerge(sourceElement, parentElement, saveMode);
 
            // Unmerge the optional attributes cache as well
            SwitchElement le = sourceElement as SwitchElement;
            if ((le != null) && (le._attributes != null))
                this._attributes = le._attributes;
        }
 
        internal void ResetProperties()
        {
            // Blow away any UnrecognizedAttributes that we have deserialized earlier.
            if (_attributes != null)
            {
                _attributes.Clear();
                _properties.Clear();
                _properties.Add(_propName);
                _properties.Add(_propValue);
            }
        }
    }
}