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 Image may be NSFW.
Clik here to view.
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>