/// <inheritdoc />
        /// <exception cref="InvalidOperationException">The <see cref="T:System.Xml.XmlReader" /> is not positioned on a recognized node type.</exception>
        /// <exception cref="XmlException">The underlying <see cref="T:System.Xml.XmlReader" /> throws an exception.</exception>
        protected override bool OnDeserializeUnrecognizedElement(string elementName, XmlReader reader)
        {
            // The base method on collections handles known elements (like add, remove, clear, <ELEMENTNAME>, etc.),
            // On sections and elements it returns false.
            if (base.OnDeserializeUnrecognizedElement(elementName, reader))
            {
                return(true);
            }

            // If we have a default collection we ask it to handle it first.
            if (_hasDefaultCollection)
            {
                IInternalConfigurationElement defaultCollection = base[string.Empty] as IInternalConfigurationElement;
                if (defaultCollection != null && defaultCollection.OnDeserializeUnrecognizedElement(elementName, reader))
                {
                    return(true);
                }
            }

            // Read the element, getting it's XName.
            XElement element    = (XElement)XNode.ReadFrom(reader);
            string   elementStr = element.ToString(SaveOptions.DisableFormatting);

            lock (_elements)
                _elements[elementName] = elementStr;

            return(true);
        }
        /// <summary>
        /// Overrides the base add method to link parents.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <exception cref="ArgumentNullException"><paramref name="element"/> is <see langword="null" />.</exception>
        /// <exception cref="ConfigurationErrorsException">The element is of the wrong type.</exception>
        protected override void BaseAdd(System.Configuration.ConfigurationElement element)
        {
            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }
            TValue value = element as TValue;

            if (value == null)
            {
                throw new ConfigurationErrorsException(
                          string.Format(
                              // ReSharper disable once AssignNullToNotNullAttribute
                              Resources.ConfigurationElement_Init_Invalid_Configuration_Property_Type,
                              element.GetType()));
            }

            TKey   key         = GetElementKey(value);
            string elementName = $"[{key}]";
            IInternalConfigurationElement ice = value;

            lock (_children)
            {
                ice.Parent = this;
                ice.ConfigurationElementName = elementName;
                _children.Add(ice);
                base.BaseAdd(element);
            }
            ((IInternalConfigurationElement)this).OnChanged(this.GetFullPath(elementName));
        }
        /// <summary>
        ///   Removes the first occurrence of a specific object from the collection.
        /// </summary>
        /// <param name="item">The element to remove from the collection.</param>
        /// <returns>
        ///   Returns <see langword="true"/> if the element was successfully removed; otherwise returns <see langword="false"/>.
        ///   This method also returns false if the element is not found.
        /// </returns>
        /// <exception cref="System.NotSupportedException">
        ///   The collection is read-only.
        /// </exception>
        bool ICollection <TValue> .Remove([NotNull] TValue item)
        {
            TKey key = GetElementKey(item);
            bool found;

            lock (_children)
            {
                TValue value = (TValue)BaseGet(key);
                if (value == null)
                {
                    found = false;
                }
                else
                {
                    IInternalConfigurationElement ice = value;
                    ice.Parent = null;
                    _children.Remove(ice);
                    BaseRemove(item);
                    found = true;
                }
            }

            ((IInternalConfigurationElement)this).OnChanged(this.GetFullPath($"[{key}]"));
            return(found);
        }
        /// <summary>
        /// Gets or sets the <see cref="System.Object"/> with the specified property name.
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        /// <returns>System.Object.</returns>
        /// <exception cref="ObjectDisposedException" accessor="get">The current section <see cref="IsDisposed">is disposed</see>.</exception>
        /// <exception cref="ObjectDisposedException" accessor="set">The current section <see cref="IsDisposed">is disposed</see>.</exception>
        /// <exception cref="ArgumentNullException" accessor="get"><paramref name="propertyName"/> is <see langword="null" /> or empty.</exception>
        /// <exception cref="ArgumentNullException" accessor="set"><paramref name="propertyName"/> is <see langword="null" /> or empty.</exception>
        private new object this[string propertyName]
        {
            get
            {
                if (propertyName == null)
                {
                    throw new ArgumentNullException(nameof(propertyName));
                }
                object value = base[propertyName];
                IInternalConfigurationElement ice = value as IInternalConfigurationElement;
                if (ice != null)
                {
                    ice.ConfigurationElementName = propertyName;
                }
                return(value);
            }
            set
            {
                if (IsDisposed)
                {
                    throw new ObjectDisposedException(ToString());
                }
                if (propertyName == null)
                {
                    throw new ArgumentNullException(nameof(propertyName));
                }

                lock (_children)
                {
                    object original = base[propertyName];
                    if (Equals(original, value))
                    {
                        return;
                    }

                    IInternalConfigurationElement ice = original as IInternalConfigurationElement;
                    if (ice != null && _children.Contains(ice))
                    {
                        _children.Remove(ice);
                        ice.Parent = null;
                    }

                    ice = value as IInternalConfigurationElement;
                    if (ice != null)
                    {
                        _children.Add(ice);
                        ice.Parent = this;
                        ice.ConfigurationElementName = propertyName;
                    }

                    base[propertyName] = value;
                }

                // Notify change handler
                ((IInternalConfigurationElement)this).OnChanged(this.GetFullPath(propertyName));
            }
        }
        // ReSharper disable once VirtualMemberNeverOverriden.Global
        public virtual TValue this[int index]
        {
            // ReSharper disable once AssignNullToNotNullAttribute
            get
            {
                TValue value = (TValue)BaseGet(index);
                if (value != null && value.ConfigurationElementName == null)
                {
                    ((IInternalConfigurationElement)value).ConfigurationElementName = $"[{GetElementKey(value)}]";
                }
                return(value);
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException(nameof(value));
                }

                TKey   originalKey;
                TKey   newKey         = GetElementKey(value);
                string newElementName = $"[{newKey}]";
                lock (_children)
                {
                    IInternalConfigurationElement ice = (IInternalConfigurationElement)BaseGet(index);
                    if (Equals(ice, value))
                    {
                        return;
                    }

                    // Cannot have null values
                    Debug.Assert(ice != null);
                    originalKey = GetElementKey((TValue)ice);
                    BaseRemoveAt(index);

                    if (_children.Contains(ice))
                    {
                        _children.Remove(ice);
                        ice.Parent = null;
                    }

                    ice = value;
                    _children.Add(ice);
                    ice.Parent = this;
                    ice.ConfigurationElementName = newElementName;
                    base.BaseAdd(index, value);
                }
                ((IInternalConfigurationElement)this).OnChanged(this.GetFullPath($"[{originalKey}]"));
                ((IInternalConfigurationElement)this).OnChanged(this.GetFullPath(newElementName));
            }
        }
        /// <inheritdoc />
        protected override void Unmerge(System.Configuration.ConfigurationElement sourceElement, System.Configuration.ConfigurationElement parentElement, ConfigurationSaveMode saveMode)
        {
            base.Unmerge(sourceElement, parentElement, saveMode);

            IInternalConfigurationElement source = sourceElement as IInternalConfigurationElement;

            if (source == null)
            {
                return;
            }

            lock (_elements)
                _elements = source.ElementsClone;
        }
        /// <summary>
        ///   Removes an element by the specified key.
        /// </summary>
        /// <param name="key">The key of the element to remove.</param>
        /// <exception cref="System.Exception">
        ///   The element does not exist in the collection, the element has already been removed,
        ///    or the element cannot be removed because the collection type is not
        ///   <see cref="System.Configuration.ConfigurationElementCollectionType">AddRemoveClearMap</see>
        /// </exception>
        // ReSharper disable once VirtualMemberNeverOverriden.Global
        public virtual void Remove([NotNull] TKey key)
        {
            lock (_children)
            {
                IInternalConfigurationElement ice = (IInternalConfigurationElement)BaseGet(key);
                if (ice == null)
                {
                    return;
                }

                ice.Parent = null;
                _children.Remove(ice);
                BaseRemove(key);
            }

            ((IInternalConfigurationElement)this).OnChanged(this.GetFullPath($"[{key}]"));
        }
        // ReSharper disable once VirtualMemberNeverOverriden.Global
        public virtual TValue this[[NotNull] TKey key]
        {
            get
            {
                TValue value = (TValue)BaseGet(key);
                if (value != null)
                {
                    ((IInternalConfigurationElement)value).ConfigurationElementName = $"[{key}]";
                }
                return(value);
            }
            set
            {
                string elementName = $"[{key}]";
                lock (_children)
                {
                    TValue original = (TValue)BaseGet(key);
                    if (Equals(original, value))
                    {
                        return;
                    }

                    IInternalConfigurationElement ice = original;

                    if (ice != null)
                    {
                        _children.Remove(original);
                        ice.Parent = null;
                    }

                    ice = value;
                    if (ice != null)
                    {
                        _children.Add(ice);
                        ice.Parent = this;
                        ice.ConfigurationElementName = elementName;
                        base.BaseAdd(value);
                    }
                }
                ((IInternalConfigurationElement)this).OnChanged(this.GetFullPath(elementName));
            }
        }
        /// <summary>
        ///   Removes the element at the specified index.
        /// </summary>
        /// <param name="index">The index of the element to remove.</param>
        /// <exception cref="ConfigurationErrorsException">
        ///   <para>The configuration is read-only.</para>
        ///   <para>-or-</para>
        ///   <para>The index is less than 0 or greater than the number of elements in the collection.</para>
        ///   <para>-or-</para>
        ///   <para>The element has already been removed.</para>
        ///   <para>-or-</para>
        ///   <para>The element has been locked at a higher level.</para>
        /// </exception>
        // ReSharper disable once VirtualMemberNeverOverriden.Global
        public virtual void RemoveAt(int index)
        {
            TKey key;

            lock (_children)
            {
                IInternalConfigurationElement ice = (IInternalConfigurationElement)BaseGet(index);
                if (ice == null)
                {
                    return;
                }

                key = GetElementKey((TValue)ice);
                _children.Remove(ice);
                ice.Parent = null;

                BaseRemove(ice);
            }
            ((IInternalConfigurationElement)this).OnChanged(this.GetFullPath($"[{key}]"));
        }
        /// <summary>
        /// Initializes this instance.
        /// </summary>
        /// <exception cref="ConfigurationErrorsException">Invalid property type.</exception>
        protected override void Init()
        {
            base.Init();
            // ReSharper disable once PossibleNullReferenceException
            // ReSharper disable once AssignNullToNotNullAttribute
            foreach (ConfigurationProperty property in Properties.Where(p => p.Type.DescendsFrom(typeof(System.Configuration.ConfigurationElement))))
            {
                Debug.Assert(property.Type != null);
                if (!property.Type.ImplementsInterface(typeof(IInternalConfigurationElement)))
                {
                    throw new ConfigurationErrorsException(
                              string.Format(
                                  // ReSharper disable AssignNullToNotNullAttribute
                                  Resources.ConfigurationElement_Init_Invalid_Configuration_Property_Type,
                                  // ReSharper restore AssignNullToNotNullAttribute
                                  property.Type));
                }

                if (property.Name.Length < 1)
                {
                    _hasDefaultCollection = true;
                }

                // Get the value or create a new element, if this is an element type that is not yet created.
                // ReSharper disable once ArrangeStaticMemberQualifier
                IInternalConfigurationElement value =
                    (IInternalConfigurationElement)(this[property.Name] ?? ConfigurationElement.Create(property.Type));

                if (value == null)
                {
                    continue;
                }

                value.Parent = this;
                value.ConfigurationElementName = property.Name;
                _children.Add(value);
            }
        }