Otro blog sobre programación en C#, grupos de usuarios .Net y más rollos tecnológicos por el estilo.

lunes 23 de febrero de 2009

Serialización dinámica con el XmlSerializer

Para acabar con esta espontanea serie de posts sobre el XmlSerializer os cuento un par de trucos no demasiado bien documentados para controlar la serialización.

En algunas ocasiones podemos necesitar que una clase hija no persista algunas de las propiedades del base, pero, como ya hemos visto antes, si la propiedad no es virtual se complica un poco el asunto. En estos casos podemos añadir un miembro público a la clase base con el mismo nombre de la propiedad + Specified con el valor a true:

public class C1
{
	public string MyProperty { get; set; }
	[XmlIgnore]
	public bool MyPropertySpecified = true;
}


De esta manera al heredar de la clase podremos especificar su valor a false, lo que hará que no se persista dicha propiedad:



public class C2:C1
{
	public string MyOtherProperty { get; set; }
	public C2()
	{
		MyPropertySpecified = false;
	}
}


En otras ocasiones, lo que querremos es decidir cuando se debe persistir el valor y cuando no. Por ejemplo, si una lista no tiene valores o si un string es null puede que no nos interese que aparezca el valor vacío en el xml. Eso se consigue con un método público llamado ShouldSerialize + el nombre de la propiedad y que devuelva un bool indicando si la propiedad debe persistirse:



public class C3 : C2
{
	public string MyThirdProperty { get; set; }
	public bool ShouldSerializeMyThirdProperty()
	{
		return false;
	}
}


Ahora podéis probar las clases, adivinad qué mostrará cada llamada:



XmlSerializer ser = new XmlSerializer(typeof(C1), 
	new Type[] { typeof(C2), typeof(C3) });
ser.Serialize(Console.Out, new C1() { MyProperty = "test"});
Console.WriteLine();
ser.Serialize(Console.Out, new C2() { MyProperty = "test", 
	MyOtherProperty = "test 2" });
Console.WriteLine();
ser.Serialize(Console.Out, new C3() { MyProperty = "test", 
	MyOtherProperty = "test 2", MyThirdProperty="test 3" });
Console.ReadLine();