Thomas Bandt

Über mich | Kontakt | Archiv

Erweiterte Serialisierung mit .NET

Wozu man Serialisierung benutzen kann und wie es funktioniert, habe ich bereits im November in einem Beispiel kurz gezeigt. Hier nun noch ein paar Erweiterungen dazu.

Verschachtelte Listen serialisieren

Richtig Spaß macht das Ganze, wenn man auch komplexe Strukturen darüber abbilden kann - wenn man beispielsweise einen kompletten Warenkorb, inklusive Liste aller bestellten Produkte und deren Eigenschaften in XML packen und so speichern kann. In der Praxis wird das vor allem dann sinnvoll, wenn man viele abweichende Felder hat, die man so allesamt etwa in der Datenbank anlegen und somit auch vorher kennen müsste.

Das Problem: Collections lassen sich nicht so einfach als Unterelemente anderer Felder serialisieren - der Serialisierer kann damit nichts anfangen. Die Lösung lautet, die Collection über ein Attribut vorher bekannt zu machen:

[XmlInclude(typeof(CarCollection))]
public class Setting
{
}

Nun kann innerhalb von Setting auch eine Liste vom Typ CarCollection, die ihrerseits in meinem Beispiel von List<Car> erbt, verwendet werden:

SettingCollection settings = new SettingCollection();

// Generate Cars
CarCollection cars = new CarCollection();
cars.Add(new Car()
{
    Color = new Color() { Name = "Silver" },
    Name = "Mercedes"
});

settings.Add(new Setting() { Key = "MyCars", Value = cars });

Heraus kommt:

<?xml version="1.0" encoding="utf-16"?>
<ArrayOfSetting xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Setting key="MyCars"> <value xsi:type="ArrayOfCar"> <Car name="Mercedes"> <color name="Silver" /> </Car> </value> </Setting> </ArrayOfSetting>

Das Schlüsselwort, oder vielmehr das Schlüsselattribut in diesem Fall Lautet XmlInclude [1].

Einfluss auf das Format des generierten XML-Codes nehmen

Man kann durchaus auch Einfluss auf das Format des generierten XML-Codes nehmen, um etwa Zeichen und damit Speicherplatz zu sparen. So kann man beispielsweise durch das Attribut XmlAttribute [2] für Properties festlegen, dass diese eben als Attribut und nicht als Node abgebildet werden - was natürlich nur dann sinnvoll ist, wenn die Property keine weiteren Elemente oder Eigenschaften enthält, beispielsweise bei Strings, Zahlen usw.

Felder ausschließen

Ebenfalls wichtig, etwa wenn man nicht alle Eigenschaften einer Klasse serialisieren möchte, ist das Attribute XmlIgnore. Eine damit versehene Eigenschaft lässt sich bei der Serialisierung schlicht "ignorieren".

Zusammenfassung

Man sollte sich nicht gleich aus der Ruhe bringen lassen, wenn der Compiler einem den eigenen Code um die Ohren schmeißt und meckert - was bei diesem Thema mit ziemlicher Wahrscheinlichkeit auftritt, wenn man die ersten Gehversuche unternimmt. Es lassen sich beispielsweise keine Objekte vom Typ Dictionary<T, T> serialisieren - aber hey, dann baut man sich eben seine eigene Collection und serialisiert diese, so what :-).

Unterm Strich halte ich das für eine wirklich sinnvolle Vorgehensweise um flexibel Daten in Strukturen zu speichern, die man zur Entwicklungszeit vielleicht noch gar nicht kennt - bzw. die man zwar kennt, man aber genau weiß, dass sie sich schnell ändern werden.

Ein kleiner Warnhinweis noch: für die Verwendung der XmlSerializer-Klasse ist zur Erstellung der temporären Klassen unbedingter Schreibzugriff auf %WinDir%\Temp notwendig - was vor allem in SharedHosting-Umgebungen problematisch werden könnte.

Verweise

[1] XmlIncludeAttribute Class
[2] XmlAttributes Class
[3] XmlIgnoreAttribute Class

Anhang

Anbei ein kleines Beispielprojekt, was alle erwähnten Beispiele beinhaltet (Web-Projekt, .NET 3.5).

Downloads



« Zurück  |  Weiter »