protected void SetXmlAttributeProcessingIndex(string attributeName, int positionIndex)
        {
            if (!_AttributeInfoCollection.Contains(attributeName))
            {
                throw new Exception("Cannot change the processing index for attribute \"" + attributeName + "\" because no such attribute has been registered.");
            }

            QXAttributeInfo <T> ai = _AttributeInfoCollection[attributeName];

            _AttributeInfoCollection.Remove(attributeName);
            _AttributeInfoCollection.Insert(positionIndex, ai);
        }
        protected void ReadXmlAttributes(T owner, XmlReader reader)
        {
            reader.MoveToElement();
            HashSet <string> encounteredAttributes = new HashSet <string>();

            int attributeCount = reader.AttributeCount;

            for (int i = 0; i < attributeCount; i++)
            {
                reader.MoveToAttribute(i);
                string attributeName  = reader.Name;
                string attributeValue = reader.Value;

                if (!_AttributeInfoCollection.Contains(attributeName))
                {
                    if (!this.IgnoreUnregisteredAttributes)
                    {
                        throw new Exception("Unregistered attribute \"" + attributeName + "\" encountered while reading attribues.");
                    }
                    else
                    {
                        continue;
                    }
                }

                QXAttributeInfo <T> attributeInfo = this.GetAttributeInfo(attributeName);
                if (attributeInfo.ProcessingMode == QXProcessingMode.Ignore)
                {
                    continue;
                }

                // Process the attribute value
                attributeInfo.Decoder(owner, attributeValue);
                encounteredAttributes.Add(attributeName);
            }

            foreach (QXAttributeInfo <T> ai in _AttributeInfoCollection)
            {
                if (ai.ProcessingMode == QXProcessingMode.Required && !encounteredAttributes.Contains(ai.AttributeName))
                {
                    throw new Exception("Required attribute \"" + ai.AttributeName + "\" not present.");
                }
            }
        }
 protected override string GetKeyForItem(QXAttributeInfo <T> item) => item.AttributeName;