Tag: .Net

XmlSerializable Generic Dictionary

I need to use generic dictionary on both JSON and XML serialization.


using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Xml;

namespace Rubik.Staging
{
[XmlSchemaProvider(“GetInternalSchema”)]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
#region IXmlSerializable Members

private const string ns = “http://www.rubik.com.tr/staging”;

public static XmlQualifiedName GetInternalSchema(XmlSchemaSet xs)
{
bool keyIsSimple = (typeof(TKey).IsPrimitive || typeof(TKey) == typeof(string));
bool valueIsSimple = (typeof(TValue).IsPrimitive || typeof(TValue) == typeof(string));

XmlSchemas schemas = new XmlSchemas();

XmlReflectionImporter importer = new XmlReflectionImporter(ns);
importer.IncludeType(typeof(TKey));
importer.IncludeType(typeof(TValue));

XmlTypeMapping keyMapping = importer.ImportTypeMapping(typeof(TKey));
XmlTypeMapping valueMapping = importer.ImportTypeMapping(typeof(TValue));

XmlSchemaExporter exporter = new XmlSchemaExporter(schemas);

if(!keyIsSimple)
exporter.ExportTypeMapping(keyMapping);
if(!valueIsSimple)
exporter.ExportTypeMapping(valueMapping);

XmlSchema schema = (schemas.Count == 0 ? new XmlSchema() : schemas[0]);

schema.TargetNamespace = ns;
XmlSchemaComplexType type = new XmlSchemaComplexType();
type.Name = “DictionaryOf” + keyMapping.XsdTypeName + “And” + valueMapping.XsdTypeName;
XmlSchemaSequence sequence = new XmlSchemaSequence();
XmlSchemaElement item = new XmlSchemaElement();
item.Name = “Item”;

XmlSchemaComplexType itemType = new XmlSchemaComplexType();
XmlSchemaSequence itemSequence = new XmlSchemaSequence();

XmlSchemaElement keyElement = new XmlSchemaElement();

keyElement.Name = “Key”;
keyElement.MaxOccurs = 1;
keyElement.MinOccurs = 1;

XmlSchemaComplexType keyType = new XmlSchemaComplexType();
XmlSchemaSequence keySequence = new XmlSchemaSequence();
XmlSchemaElement keyValueElement = new XmlSchemaElement();
keyValueElement.Name = keyMapping.ElementName;
keyValueElement.SchemaTypeName = new XmlQualifiedName(keyMapping.XsdTypeName, keyMapping.XsdTypeNamespace);
keyValueElement.MinOccurs = 1;
keyValueElement.MaxOccurs = 1;
keySequence.Items.Add(keyValueElement);
keyType.Particle = keySequence;
keyElement.SchemaType = keyType;
itemSequence.Items.Add(keyElement);

XmlSchemaElement valueElement = new XmlSchemaElement();

valueElement.Name = “Value”;
valueElement.MaxOccurs = 1;
valueElement.MinOccurs = 1;

XmlSchemaComplexType valueType = new XmlSchemaComplexType();
XmlSchemaSequence valueSequence = new XmlSchemaSequence();
XmlSchemaElement valueValueElement = new XmlSchemaElement();
valueValueElement.Name = valueMapping.ElementName;
valueValueElement.SchemaTypeName = new XmlQualifiedName(valueMapping.XsdTypeName, valueMapping.XsdTypeNamespace);
valueValueElement.MinOccurs = 1;
valueValueElement.MaxOccurs = 1;
valueSequence.Items.Add(valueValueElement);
valueType.Particle = valueSequence;
valueElement.SchemaType = valueType;
itemSequence.Items.Add(valueElement);
itemType.Particle = itemSequence;
item.SchemaType = itemType;
sequence.Items.Add(item);
type.Particle = sequence;
schema.Items.Add(type);

xs.XmlResolver = new XmlUrlResolver();
xs.Add(schema);

return new XmlQualifiedName(type.Name, ns);
}

public void ReadXml(System.Xml.XmlReader reader)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

bool wasEmpty = reader.IsEmptyElement;
reader.Read();

if (wasEmpty)
return;

while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
{
reader.ReadStartElement(“Item”);

reader.ReadStartElement(“Key”);
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();

reader.ReadStartElement(“Value”);
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();

this.Add(key, value);

reader.ReadEndElement();

reader.MoveToContent();
}

reader.ReadEndElement();
}

public void WriteXml(System.Xml.XmlWriter writer)
{
XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

foreach (TKey key in this.Keys)
{
writer.WriteStartElement(“Item”);

writer.WriteStartElement(“Key”);
keySerializer.Serialize(writer, key);
writer.WriteEndElement();

writer.WriteStartElement(“Value”);
TValue value = this[key];
valueSerializer.Serialize(writer, value);
writer.WriteEndElement();

writer.WriteEndElement();
}
}

#endregion

#region IXmlSerializable Members

public XmlSchema GetSchema()
{
return null;
}

#endregion
}

}