OrderedDictionary

Dictionary with ordered keys.
One c# (4.0) class which implements ICollection, IDictionary, IList and IXmlSerializable.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace System.Collection.Generic
{
    [Serializable]
    public class OrderedDictionary : 
        ICollection>, 
        IDictionary, 
        IList>, 
        System.Xml.Serialization.IXmlSerializable
    {
        List keys;
        Dictionary dict;

        #region Constructors
        /// 
        /// Initializes a new instance of the OrderedDictionary class that is empty and has the default initial capacity. 
        /// 
        public OrderedDictionary()
        {
            keys = new List();
            dict = new Dictionary();
        }

        /// 
        /// Initializes a new instance of the OrderedDictionary class that is empty and has the specified initial capacity. 
        /// 
        /// The number of elements that the new dictionary can initially store.
        public OrderedDictionary(int capacity)
        {
            keys = new List(capacity);
            dict = new Dictionary(capacity);
        }

        /// 
        /// Initializes a new instance of the OrderedDictionary class that contains elements copied from the specified collection and has sufficient capacity to accommodate the number of elements copied. 
        /// 
        /// The collection whose elements are copied to the new dictionary.
        public OrderedDictionary(IEnumerable> collection)
        {
            keys = new List();
            dict = new Dictionary();
            var enumerator = collection.GetEnumerator();
            while (enumerator.MoveNext())
            {
                keys.Add(enumerator.Current.Key);
                dict.Add(enumerator.Current.Key, enumerator.Current.Value);
            }
        }

        /// 
        /// Initializes a new instance of the OrderedDictionary class that contains elements copied from the specified OrderedDictionary or Dictionary and uses the default equality comparer for the key type. 
        /// 
        /// The OrderedDictionary or Dictionary whose elements are copied to the new OrderedDictionary.
        public OrderedDictionary(IDictionary dictionary)
        {
            keys = new List();
            dict = new Dictionary();
            foreach (var item in dictionary)
            {
                keys.Add(item.Key);
                dict.Add(item.Key, item.Value);
            }
        }
        #endregion

        #region Add / Insert
        /// 
        /// Adds an item to the OrderedDictionary. 
        /// 
        /// The object to add to the OrderedDictionary.
        public void Add(KeyValuePair item)
        {
            dict.Add(item.Key, item.Value);
            keys.Add(item.Key);
        }

        /// 
        /// Adds an element with the provided key and value to the OrderedDictionary.
        /// 
        /// The object to use as the key of the element to add.
        /// The object to use as the value of the element to add.
        public void Add(TKey key, TValue value)
        {
            dict.Add(key, value);
            keys.Add(key);
        }

        /// 
        /// Inserts an item to the OrderedDictionary at the specified index. 
        /// 
        /// The zero-based index at which item should be inserted.
        /// The object to insert into the OrderedDictionary
        public void Insert(int index, KeyValuePair item)
        {
            dict.Add(item.Key, item.Value);
            keys.Insert(index, item.Key);
        }

        /// 
        /// Inserts an element with the provided key and value to the OrderedDictionary at the specified index. 
        /// 
        /// The zero-based index at which item should be inserted.
        /// The object to use as the key of the element to inserted.
        /// The object to use as the value of the element to inserted.
        public void Insert(int index, TKey key, TValue value)
        {
            dict.Add(key, value);
            keys.Insert(index, key);
        }

        /// 
        /// Gets the value associated with the specified key.
        /// 
        /// The key whose value to get.
        /// When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the value parameter. This parameter is passed uninitialized. 
        /// true if the object that implements OrderedDictionary contains an element with the specified key; otherwise, false.
        public bool TryGetValue(TKey key, out TValue value)
        {
            return dict.TryGetValue(key, out value);
        }
        #endregion

        #region Remove / RemoveAt
        /// 
        /// Removes all items from the OrderedDictionary.
        /// 
        public void Clear()
        {
            dict.Clear();
            keys.Clear();
        }

        /// 
        /// Removes the specific object from the OrderedDictionary. The value property will be ignored.
        /// 
        /// The object to remove from the OrderedDictionary.
        /// true if item was successfully removed from the OrderedDictionary; otherwise, false. This method also returns false if item is not found in the original OrderedDictionary.
        public bool Remove(KeyValuePair item)
        {
            if (keys.Remove(item.Key))
            {
                return dict.Remove(item.Key);
            }
            else
            {
                return false;
            }
        }

        /// 
        /// Removes the element with the specified key from the OrderedDictionary.
        /// 
        /// The key of the element to remove.
        /// true if the element is successfully removed; otherwise, false. This method also returns false if key was not found in the original OrderedDictionary.
        public bool Remove(TKey key)
        {
            if (keys.Remove(key))
            {
                return dict.Remove(key);
            }
            else
            {
                return false;
            }
        }

        /// 
        /// Removes the OrderedDictionary item at the specified index. 
        /// 
        /// The zero-based index of the item to remove.
        public void RemoveAt(int index)
        {
            var key = keys[index];
            keys.RemoveAt(index);
            dict.Remove(key);
        }
        #endregion

        #region Count / Contains / IndexOf
        /// 
        /// Gets the number of elements contained in the OrderedDictionary. 
        /// 
        public int Count
        {
            get { return keys.Count(); }
        }

        /// 
        /// Determines whether the OrderedDictionary contains a specific value. The value property will be ignored.
        /// 
        /// The object to locate in the OrderedDictionary.
        /// true if item is found in the OrderedDictionary; otherwise, false. 
        public bool Contains(KeyValuePair item)
        {
            return keys.Contains(item.Key);
        }

        /// 
        /// Determines whether the OrderedDictionary contains an element with the specified key. 
        /// 
        /// The key to locate in the OrderedDictionary.
        /// true if the IOrderedDictionary contains an element with the key; otherwise, false. 
        public bool ContainsKey(TKey key)
        {
            return keys.Contains(key);
        }

        /// 
        /// Determines the index of a specific item in the OrderedDictionary.
        /// 
        /// The key to locate in the OrderedDictionary.
        /// The index of key if found in the list; otherwise, -1.
        public int IndexOf(TKey key)
        {
            return keys.IndexOf(key);
        }

        /// 
        /// Determines the index of a specific item in the OrderedDictionary. The value property will be ignored.
        /// 
        /// The item to locate in the OrderedDictionary.
        /// The index of item if found in the list; otherwise, -1.
        public int IndexOf(KeyValuePair item)
        {
            return keys.IndexOf(item.Key);
        }
        #endregion

        #region Misc
        /// 
        /// Apply the new comparer to OrderedDictionary.
        /// 
        /// The IEqualityComparer implementation to use when comparing keys, or null to use the default EqualityComparer for the type of the key.
        public void ApplyComparer(IEqualityComparer comparer)
        {
            var newDict = new Dictionary(keys.Count, comparer);
            var newKeys = new List(keys.Count);
            foreach (var key in keys)
            {
                newDict.Add(key, dict[key]);
                newKeys.Add(key);
            }
            keys = newKeys;
            dict = newDict;
        }

        /// 
        /// Gets a value indicating whether the OrderedDictionary is read-only. Value false will be returned always.
        /// 
        public bool IsReadOnly
        {
            get { return false; }
        }

        /// 
        /// Copies the elements of the OrderedDictionary to an Array, starting at a particular Array index. 
        /// 
        /// The one-dimensional Array that is the destination of the elements copied from OrderedDictionary. The Array must have zero-based indexing.
        /// The zero-based index in array at which copying begins. 
        public void CopyTo(KeyValuePair[] array, int arrayIndex)
        {
            int index = arrayIndex;
            foreach (var key in keys)
            {
                array[index++] = new KeyValuePair(key, dict[key]);
            }
        }
        #endregion

        #region Enumerator
        /// 
        /// Returns an enumerator that iterates through the collection. 
        /// 
        /// An IEnumerator that can be used to iterate through the collection.
        public IEnumerator> GetEnumerator()
        {
            return (from key in keys
                    select new KeyValuePair(key, dict[key]))
                    .GetEnumerator();
        }

        /// 
        /// Returns an enumerator that iterates through the collection. 
        /// 
        /// An IEnumerator that can be used to iterate through the collection.
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        /// 
        /// Returns an enumerator that iterates through the collection. 
        /// 
        /// An IEnumerator that can be used to iterate through the collection.
        IEnumerator> IEnumerable>.GetEnumerator()
        {
            return GetEnumerator();
        }

        /// 
        /// Returns an enumerator that iterates through the keys collection.
        /// 
        /// An IEnumerator that can be used to iterate through the keys collection.
        public IEnumerator GetKeysEnumerator()
        {
            return keys.GetEnumerator();
        }
        #endregion

        #region Collection
        /// 
        /// Gets an ICollection containing the keys of the OrderedDictionary.
        /// 
        public ICollection Keys
        {
            get { return new ReadOnlyCollection(keys); }
        }

        /// 
        /// Gets an ICollection containing the values of the OrderedDictionary.
        /// 
        public ICollection Values
        {
            get
            {
                return new ReadOnlyCollection
                    ((from key in keys
                      select dict[key]).ToList());
            }
        }
        #endregion

        #region indexer
        /// 
        /// Gets or sets the element with the specified key.
        /// 
        /// The key of the element to get or set.
        /// The value which linked to the specified key.
        public TValue this[TKey key]
        {
            get
            {
                return dict[key];
            }
            set
            {
                dict[key] = value;
            }
        }

        /// 
        /// Gets the value at the specified index.
        /// 
        /// The zero-based index of the value to get or set.
        /// The value at the specified index.
        TValue this[int index]
        {
            get
            {
                return dict[keys[index]];
            }
            set
            {
                dict[keys[index]] = value;
            }
        }

        /// 
        /// Gets the element at the specified index. The method set is not supported.
        /// 
        /// The zero-based index of the element to get.
        /// The element at the specified index.
        KeyValuePair IList>.this[int index]
        {
            get
            {
                var key = keys[index];
                return new KeyValuePair(key, dict[key]);
            }
            set
            {
                throw new NotSupportedException();
            }
        }

        /// 
        /// Gets the key at the specified index.
        /// 
        /// The zero-based index of the key to get.
        /// The key at the specified index.
        public TKey GetKeyOfIndex(int index)
        {
            return keys[index];
        }
        #endregion

        #region Serialization
        /// 
        /// This method is reserved and should not be used. When implementing the IXmlSerializable interface, you should return Nothing( Nothing in Visual Basic) from this method, and instead, if specifying a custom schema is required, apply the XmlSchemaProviderAttribute to the class.
        /// 
        /// An XmlSchema that describes the XML representation of the object that is produced by the WriteXml method and consumed by the ReadXml method.
        public Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        /// 
        /// Generates an object from its XML representation.
        /// 
        /// The XmlReader stream from which the object is deserialized.
        public void ReadXml(Xml.XmlReader reader)
        {
            System.Xml.Serialization.XmlSerializer keySer = new System.Xml.Serialization.XmlSerializer(typeof(TKey));
            System.Xml.Serialization.XmlSerializer valueSer = new System.Xml.Serialization.XmlSerializer(typeof(TValue));
            reader.Read();
            reader.ReadStartElement("OrderedDictionary");
            if (reader.NodeType == System.Xml.XmlNodeType.EndElement)
                reader.ReadEndElement();
            else
            {
                while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
                {
                    reader.ReadStartElement("Item");
                    reader.ReadStartElement("Key");
                    TKey key = (TKey)keySer.Deserialize(reader);
                    reader.ReadEndElement();
                    reader.ReadStartElement("Value");
                    TValue value = (TValue)valueSer.Deserialize(reader);
                    reader.ReadEndElement();
                    dict.Add(key, value);
                    keys.Add(key);
                    reader.ReadEndElement();
                    reader.MoveToContent();
                }
                reader.ReadEndElement();
                reader.ReadEndElement();
            }
        }

        /// 
        /// Converts an object into its XML representation.
        /// 
        /// The XmlWriter stream to which the object is serialized.
        public void WriteXml(Xml.XmlWriter writer)
        {
            System.Xml.Serialization.XmlSerializer keySer = new System.Xml.Serialization.XmlSerializer(typeof(TKey));
            System.Xml.Serialization.XmlSerializer valueSer = new System.Xml.Serialization.XmlSerializer(typeof(TValue));
            writer.WriteStartElement("OrderedDictionary");
            if (Keys.Count > 0)
                foreach (TKey key in keys)
                {
                    writer.WriteStartElement("Item");
                    writer.WriteStartElement("Key");
                    keySer.Serialize(writer, key);
                    writer.WriteEndElement();
                    writer.WriteStartElement("Value");
                    valueSer.Serialize(writer, dict[key]);
                    writer.WriteEndElement();
                    writer.WriteEndElement();
                }
            writer.WriteEndElement();
        }
        #endregion
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *