Skip to main content

Note: This post is part of a series and you can find the rest of the parts in the series index.

For my WI adapter I needed an implementation of Dictionary<T,V> which could be serialised and unfortunately the .NET one can’t. So I threw together a simple implementation of one using two List<T>. It is not perfect for every possible time you may need an alternative to Dictionary<T,V>, for example the only item manipulation I have is to add an item and clear all items, but it is great for my needs in the case:

[XmlRoot("simpleDictionary")]
public class SimpleDictionary<Key, Value> : IEnumerable, IXmlSerializable
{
    private List<Key> keys = new List<Key>();
    private List<Value> values = new List<Value>();

    public List<Key> Keys
    {
        get
        {
            return keys;
        }
    }

    public List<Value> Values
    {
        get
        {
            return values;
        }
    }

    public IEnumerator GetEnumerator()
    {
        return (IEnumerator)new SimpleDictionaryEnumerator(this);
    }

    public void Add(Key key, Value value)
    {
        keys.Add(key);
        values.Add(value);
    }

    public void Add(object o)
    {
        KeyValuePair<Key, Value>? keyValuePair = o as KeyValuePair<Key, Value>?;
        if (keyValuePair != null)
        {
            this.Add(keyValuePair.Value.Key, keyValuePair.Value.Value);
        }
    }

    public void Clear()
    {
        keys.Clear();
        values.Clear();
    }

    #endregion

    private class SimpleDictionaryEnumerator : IEnumerator
    {
        private SimpleDictionary<Key, Value> simpleDictionary;
        private int index = -1;

        public SimpleDictionaryEnumerator(SimpleDictionary<Key, Value> simpleDictionary)
        {
            this.simpleDictionary = simpleDictionary;
        }

        #region IEnumerator Members

        public object Current
        {
            get
            {
                return new KeyValuePair<Key, Value>(simpleDictionary.keys[index], simpleDictionary.values[index]);
            }
        }

        public bool MoveNext()
        {
            index++;
            return !(index >= simpleDictionary.keys.Count);

        }

        public void Reset()
        {
            index = -1;
        }
    }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        if (reader.IsEmptyElement)
        {
            return;
        }

        XmlSerializer keySerialiser = new XmlSerializer(typeof(Key));
        XmlSerializer valueSerialiser = new XmlSerializer(typeof(Value));

        reader.Read();
        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
            reader.ReadStartElement("keyValuePair");

            reader.ReadStartElement("key");
            Key key = (Key)keySerialiser.Deserialize(reader);
            reader.ReadEndElement();

            reader.ReadStartElement("value");
            Value value = (Value)valueSerialiser.Deserialize(reader);
            reader.ReadEndElement();

            this.Add(key, value);

            reader.ReadEndElement(); // for keyvaluepair
            reader.MoveToContent();
        }

        reader.ReadEndElement(); // for root
    }

    public void WriteXml(XmlWriter writer)
    {
        XmlSerializer keySerialiser = new XmlSerializer(typeof(Key));
        XmlSerializer valueSerialiser = new XmlSerializer(typeof(Value));

        for (int counter = 0; counter < this.keys.Count; counter++)
        {
            writer.WriteStartElement("keyValuePair");

            writer.WriteStartElement("key");
            keySerialiser.Serialize(writer, this.keys[counter]);
            writer.WriteEndElement();

            writer.WriteStartElement("value");
            valueSerialiser.Serialize(writer, this.values[counter]);
            writer.WriteEndElement();

            writer.WriteEndElement();

        }
    }
}