Daily Archives: 7.9.2011

XmlSerializer verwenden mit abgeleiteten Klassen ohne “xsi:type” im XML zu verwenden

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>