Serializar Dictionay usando Framework 3.0 - WCF
Para aquellos que hayan intentado serializar un diccionario con el Framework 2.x (o inferiores), se habrán encontrado con un maravilloso error de que ello no es posible por defecto. ¿Pero si puedo serializar una lista de tipos complejos, tal que List<MiTipo>, por qué no voy a poder serializar un diccionario que es 3/4 de lo mismo? Este problema digamos que se nos escapa de nuestras manos humildes y tendríamos que preguntarselo a los chichos de Redmon, ya que el problema se encuentra dentro del Framework.
Una tipo que quiera ser serializable debe implementar IXmlSerializable, lo cual no lo hace la clase Dictionary, ¿por qué? This is the question. Dicha clase se encuentra en la librería mscorlib.dll y IXmlSerializable en System.Xml.dll, no pudiendo haber dependencias de la primera a la segunda, ya que se crearía una referencia circular (System.Xml ya hace uso de mscorlib).
Para subsanar dicho problema con el Framework 2.x acudíamos al truco del almendruco: creabamos nuestra propia clase Diccionario la cual heredara de Dictionary e implementara IXmlSerializable, algo tal que así:
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue>
: Dictionary<TKey, TValue>, IXmlSerializable
{ ....
}
Podeis encontrar un ejemplo completo de ello en http://weblogs.asp.net/pwelter34/archive/2006/05/0...
------------------------------------------------
Con la llegada del Framework 3.x, este problema queda solucionado, dándonos soporte el módulo de WCF (Windows Communication Foundation). Concretamente, la librería System.Runtime.Serialization del Framework 3.0 nos proporciona las entidades XmlDictionaryWriter y DataContractSerializer.
Si ahondamos un poco más en la cuestión, veremos como los desarrolladores del Framework 3.0 han solucionado el problema de la posible referecia circular antes comentanda, incorporando la clase XmlDictionaryWriter al ensamblado System.Runtime.Serialization.dll con en el espacio de nombre System.Xml, en lugar de incorporarla al ensamblado supuestamente correspondiente System.XML.dll
La clase DataContractSerializer es la entidad similar a XmlSerializer, encargada de serializar los diccionarios a traves de XmlDictionaryWriter.
Veamos para terminar un poco de código, donde serializaremos un Diccionario de tipos simples. En el próximo post, para no alargar más éste, serializaremos y deserializaremos un diccionario con tipos complejos.
Dictionary<string, string> mundo = new Dictionary<string, string>();
mundo.Add("coche", "renault");mundo.Add("animal", "gato");
XmlWriterSettings setting = new XmlWriterSettings();
setting.Indent = true;
XmlWriter xtw = XmlTextWriter.Create("c:/mundo.xml", setting);
XmlDictionaryWriter xdw = XmlDictionaryWriter.CreateDictionaryWriter(xtw);
System.Runtime.Serialization.DataContractSerializer dcs = new DataContractSerializer(typeof(Dictionary<string, string>));
dcs.WriteObject(xdw, mundo);
xtw.Close();
Si nos vamos a C:/ veremos el nuevo archivo mundo.xml con el siguiente contenido:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfKeyValueOfstringstring xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<KeyValueOfstringstring>
<Key>coche</Key>
<Value>renault</Value>
</KeyValueOfstringstring>
<KeyValueOfstringstring>
<Key>animal</Key>
<Value>gato</Value>
</KeyValueOfstringstring>
</ArrayOfKeyValueOfstringstring>