serialize dictionary<string, string> collection in .net3.5

  • Thread starter Thread starter Andy B
  • Start date Start date
Got any simular ideas that can be used for that type of thing. More or less
a key/value string pair that can be serialized?
 
Not sure if this is a great idea, but it works:

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.ComponentModel;
using System.Collections.Specialized;

class Program
{
static void Main()
{
Foo foo = new Foo
{
Values =
{
{ "abc", "def" },
{ "ghi", "jkl" }
}
};
XmlSerializer ser = new XmlSerializer(typeof(Foo));
StringWriter writer = new StringWriter();
ser.Serialize(writer, foo);
string xml = writer.ToString();

StringReader reader = new StringReader(xml);
Foo newFoo = (Foo) ser.Deserialize(reader);
foreach (KeyValuePair<string, string> pair in newFoo.Values)
{
Console.WriteLine(pair.Key + ": " + pair.Value);
}
}
}

[Serializable]
public class Foo
{
private readonly Dictionary<string, string> values
= new Dictionary<string,string>();
[XmlIgnore]
public Dictionary<string, string> Values { get { return
values; } }

[EditorBrowsable(EditorBrowsableState.Never)]
[XmlArray(ElementName="Values")]
[XmlArrayItem(ElementName="Add", Type=typeof(StringPair))]
public StringPairList ValuesProxy
{
get { return new StringPairList(values); }
}
}

[Serializable]
public class StringPairList : IList<StringPair>
{
private readonly IDictionary<string,string> parent;
public StringPairList(IDictionary<string, string> parent)
{
if (parent == null) throw new ArgumentNullException("parent");
this.parent = parent;
}

#region IList<StringPair> Members

public int IndexOf(StringPair item)
{
throw new NotImplementedException();
}

public void Insert(int index, StringPair item)
{
throw new NotImplementedException();
}

public void RemoveAt(int index)
{
throw new NotImplementedException();
}

public StringPair this[int index]
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}

#endregion

#region ICollection<StringPair> Members

public void Add(StringPair item)
{
parent.Add(item.Key, item.Value);
}

public void Clear()
{
parent.Clear();
}

public bool Contains(StringPair item)
{
throw new NotImplementedException();
}

public void CopyTo(StringPair[] array, int arrayIndex)
{
throw new NotImplementedException();
}

public int Count
{
get { return parent.Count; }
}

public bool IsReadOnly
{
get { return false; }
}

public bool Remove(StringPair item)
{
throw new NotImplementedException();
}

#endregion

#region IEnumerable<StringPair> Members

public IEnumerator<StringPair> GetEnumerator()
{
foreach (var pair in parent)
{
yield return new StringPair
{
Key = pair.Key,
Value = pair.Value
};
}
}

#endregion

#region IEnumerable Members

System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

#endregion
}

[Serializable]
public class StringPair
{
[XmlAttribute]
public string Key { get; set; }
[XmlAttribute]
public string Value { get; set; }
}
 
Actually, it looks like it only needs IEnumerable<StringPair>
and Add(StringPair) - I incorrectly assumed it would use the
Add method from IList<StringPair> (in fact it finds the Add
separately); removing all the dross
makes the solution far less grungy - satisfactory, even.

Example (K&R for brevity):

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Xml.Serialization;

static class Program {
static void Main() {
Foo foo = new Foo {
Values = {
{ "abc", "def" },
{ "ghi", "jkl" }
}
};
XmlSerializer ser = new XmlSerializer(typeof(Foo));
StringWriter writer = new StringWriter();
ser.Serialize(writer, foo);
string xml = writer.ToString();

StringReader reader = new StringReader(xml);
Foo newFoo = (Foo) ser.Deserialize(reader);
foreach (KeyValuePair<string, string> pair in newFoo.Values) {
Console.WriteLine(pair.Key + ": " + pair.Value);
}
}
}

[Serializable]
public class Foo {
private readonly Dictionary<string, string> values
= new Dictionary<string,string>();
[XmlIgnore]
public Dictionary<string, string> Values { get { return
values; } }

[EditorBrowsable(EditorBrowsableState.Never)]
[XmlArray(ElementName="Values")]
[XmlArrayItem(ElementName="add", Type=typeof(StringPair))]
public StringPairList ValuesProxy {
get { return new StringPairList(values); }
}
}
[Serializable]
public sealed class StringPairList : IEnumerable<StringPair> {
private readonly IDictionary<string,string> parent;
public StringPairList(IDictionary<string, string> parent) {
if (parent == null) throw new ArgumentNullException("parent");
this.parent = parent;
}
public void Add(StringPair item) {
parent.Add(item.Key, item.Value);
}
public IEnumerator<StringPair> GetEnumerator() {
foreach (var pair in parent) {
yield return new StringPair {
Key = pair.Key, Value = pair.Value
};
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}

[Serializable]
public sealed class StringPair {
[XmlAttribute("key")]
public string Key { get; set; }
[XmlAttribute("value")]
public string Value { get; set; }
}
 
There is the SerializableDictionary class that I pointed someone to last
week. I don't recall if you were in that discussion. If not, the link is
http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx.

I must have skipped that one ;-p
It looks like another viable solution; one caveat with
SerializableDictionary is that the schema isn't very well defined (in
terms of a WSDL or similar - I believe it uses "any") - but it will
work. And less effort than adding attributes and a facade property...

Marc
 
Back
Top