All I wanted to do was simple: add a setting to the application config which held a list of the most recently used file names, complete with a user created template to process the file - so they didn't have to repeat work.
Since it is going in the config file (which is XML), it made sense to use the
XmlSerializer
. Easy:
Dictionary<string, string> recentFiles;
...
xml.Serialize(memoryStream, recentFiles);
Ah.
IDictionary
not supported. MSDN says:
"The XmlSerializer cannot process classes implementing the IDictionary interface. This was partly due to schedule constraints and partly due to the fact that a hashtable does not have a counterpart in the XSD type system. The only solution is to implement a custom hashtable that does not implement the IDictionary interface."
In layman speak: "We ran out of time".
OK, an
IDictionary
is a with-frills
List
of
KeyValuePairs
- I will convert it and rebuild...
XmlSerializer
does not complain about
KeyValuePair
items. Great! Only problem is that it stores everything except the actual and / or value information...
KeyValuePair<string, string> kvp = new KeyValuePair<string, string>("My Key", "MyValue");
using (MemoryStream xml = new MemoryStream())
{
var serializer = new XmlSerializer(typeof(KeyValuePair<string, string>));
serializer.Serialize(xml, kvp);
xml.Seek(0, 0);
byte[] bytes = xml.GetBuffer();
string serialized = System.Text.Encoding.ASCII.GetString(bytes);
}
Generates:
<KeyValuePairOfStringString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
So, a brute force and ignorance approach: create a new class, that can do it:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.IO;
using System.Xml.Serialization;
namespace MyNamespace
{
[Serializable]
public class SerialPair<K, V>
{
#region Properties
public K Key { get; set; }
public V Value { get; set; }
#endregion
#region Constructors
public SerialPair()
{
}
public SerialPair(KeyValuePair<K, V> kvp)
{
Key = kvp.Key;
Value = kvp.Value;
}
public SerialPair(K key, V value)
{
Key = key;
Value = value;
}
static SerialPair()
{
if (!typeof(K).IsSerializable && !(typeof(K) is ISerializable))
{
throw new InvalidOperationException("A serializable Type is required");
}
if (!typeof(V).IsSerializable && !(typeof(V) is ISerializable))
{
throw new InvalidOperationException("A serializable Type is required");
}
}
#endregion
#region Public Methods
public static Dictionary<K, V> DeserializeDictionary(string s)
{
Dictionary<K, V> regeneratedTemplates;
List<SerialPair<K, V>> list;
byte[] combinedBytes = System.Text.Encoding.ASCII.GetBytes(s);
using (MemoryStream sr = new MemoryStream(combinedBytes))
{
XmlSerializer deserializer = new XmlSerializer(typeof(List<SerialPair<K, V>>));
list = (List<SerialPair<K, V>>)deserializer.Deserialize(sr);
regeneratedTemplates = new Dictionary<K, V>();
foreach (SerialPair<K, V> pair in list)
{
regeneratedTemplates.Add(pair.Key, pair.Value);
}
}
return regeneratedTemplates;
}
public static string SerializeDictionary(Dictionary<K, V> dict)
{
string s;
List<SerialPair<K, V>> list = new List<SerialPair<K, V>>(dict.Count);
foreach (KeyValuePair<K, V> kvp in dict.ToArray())
{
SerialPair<K, V> sp = new SerialPair<K, V>(kvp);
list.Add(sp);
}
using (MemoryStream xml = new MemoryStream())
{
XmlSerializer serializer = new XmlSerializer(typeof(List<SerialPair<K, V>>));
serializer.Serialize(xml, list);
xml.Seek(0, 0);
byte[] bytes = xml.GetBuffer();
s = System.Text.Encoding.ASCII.GetString(bytes);
}
return s;
}
#endregion
}
}
There is probably a much, much nicer way to do this (I could have used a collection that
XmlSerializer
does support, for example) but at least this way
I won't forget that it doesn't work and try using it again...
[edit]Error in XML Comment to SerialPair(K, V) constructor caused compilation warning. Fixed - OriginalGriff[/edit]
Born at an early age, he grew older. At the same time, his hair grew longer, and was tied up behind his head.
Has problems spelling the word "the".
Invented the portable cat-flap.
Currently, has not died yet. Or has he?