Lange habe ich gerätselt, wie man verhindern kann, dass der XmlSerializer bei abgeleiteten Klassen immer nur als Element-Name die Basisklasse verwendet und dann im Attribute “xsi:type” den jeweiligen richtigen Typ reinschreibt/ausliest. Das sieht im XML immer sehr unschön aus:
<Liste>
<BasisKlasse xsi:type="Ableitung01" />
<BasisKlasse xsi:type="Ableitung02" />
</Liste>
Viel schöner wäre es ja, wenn direkt die abgeleitete Klasse in der Datei stehen würde:
<Liste>
<Ableitung01 />
<Ableitung02 />
</Liste>
Bisher hab ich sowas immer gemacht, indem ich das “XmlInclude” Attribut an die Root-Klasse rangehängt habe, um dem XmlSerializer mitzuteilen, welche Klassen er noch berücksichtigen soll. Heute hat mir nun ein Kollege ganz nebenbei eine XML-Datei gezeigt, die genau das hat, was ich schon lange suche… Der Trick ist einfach nur, das “XmlArrayItem” Attribut an dem jeweiligen Property der Liste dranzuhängen… damit werden die Listen-Einträge dann ohne “xsi:type” serialisiert und bekommen den lesbaren Namen 😉
Hier ein kurzes Beispiel wie sowas aussieht:
using System.Collections.Generic;
using System.Xml.Serialization;
namespace ConsoleApplication_VS2010
{
public abstract class BaseObject {}
public class Special01 : BaseObject {}
public class Special02 : BaseObject {}
public class Root
{
readonly List<BaseObject> _Objects = new List<BaseObject>();
[XmlArrayItem(typeof(Special01))]
[XmlArrayItem(typeof(Special02))]
public List<BaseObject> Objects
{ get { return _Objects; } }
}
class Program
{
static void Main(string[] args)
{
var r = new Root();
r.Objects.Add(new Special01());
r.Objects.Add(new Special02());
r.Objects.Add(new Special01());
using (var sw = new System.IO.StringWriter())
{
var ser = new XmlSerializer(typeof (Root));
ser.Serialize(sw, r);
System.Console.WriteLine(sw.ToString());
}
}
}
}
Dies ergibt dann:
<?xml version="1.0" encoding="utf-16"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://ww
w.w3.org/2001/XMLSchema">
<Objects>
<Special01 />
<Special02 />
<Special01 />
</Objects>
</Root>