Entwickler-Ecke

C# & .NET Tutorials - Mit XmlSerializer Objekte als XML speichern und laden


UGrohne - Mi 27.09.06 22:51
Titel: Mit XmlSerializer Objekte als XML speichern und laden
Der XmlSerializer
Der XmlSerializer setzt Objekteigenschaften, die die als public deklariert sind, in XML um und umgekehrt.
Beispielsweise haben wir folgende Klassendeklaration:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
public class MyClass
{
    private string test1;
    public string Test1
    {
        get { return test1; }
        set { test1 = value; }
    }
    private string privateString;
    public string publicString;

    public MyClass()
    {
        test1 = "Teststring mit get/set-Methoden";
        privateString = "Private String";
        publicString = "Public String";
    }
}

Serialisieren des Objekts
Wir erzeugen im folgenden Code nun eine Instanz des Objekts und serialisieren diese mittels des XmlWriters in eine XML-Datei, die anschließen in einer TextBox angezeigt wird:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
//Serialize
MyClass test = new MyClass();
XmlWriterSettings xws = new XmlWriterSettings();
xws.Indent = true;
xws.IndentChars = "  ";
XmlWriter xw = XmlWriter.Create("test.xml",xws);
XmlSerializer xs = new XmlSerializer(typeof(MyClass));
xs.Serialize(xw, test);
xw.Close();

//Show XML-File
StreamReader sr = File.OpenText("test.xml");
textBox1.Text = sr.ReadToEnd();

Die Instanz von XmlWriterSettings sorgt dabei für eine lesbarere Darstellung, mit Zeilenumbrüchen und Einrückungen (Indent), der XmlWriter übernimmt das Schreiben in die Datei test.xml.

Danach wird eine XmlSerializer-Instanz erzeugt, der die eigentliche Klassendeklaration übergeben wird, damit diese das Objekt kennt.

Dem anschließenden Aufruf von Serialize wird der XmlWriter (oder eine andere ausgebende Instanz eines unterstützen Objekts) und die zu serialisierende Objektinstanz übergeben.

Die Datei test.xml enthält daraufhin folgende Zeilen:

XML-Daten
1:
2:
3:
4:
5:
<?xml version="1.0" encoding="utf-8"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <publicString>Public String</publicString>
  <Test1>Teststring mit get/set-Methoden</Test1>
</MyClass>

Hier sehen wir, dass wie oben beschrieben das öffentliche property Test1 und der öffentliche String publicString serialisiert wurden.

Deserialisieren
Natürlich können wir diesen Weg auch umgekehrt gehen und das Objekt wieder aus der XML-Datei mit Daten befüllen. Dazu benötigen wir lediglich eine Objektvariable des Zieltyps, einen StreamReader (oder auch XmlReader) und den XmlSerializer:

C#-Quelltext
1:
2:
3:
MyClass test;
XmlSerializer xs = new XmlSerializer(typeof(MyClass));
test = (MyClass) xs.Deserialize(new StreamReader("test.xml"));

Und schon hat man wieder ein befülltes Objekt.

Anmerkungen
Diese Vorgehensweise kann auch mit Klassen verwendet werden, die Unterklassen enthalten und diese veröffentlichen.

Wenn wir beispielweise eine public-Variable vom Typ MyClass2 in MyClass hätten, würde diese auch serialisiert werden, mit den Daten in einem Unterknoten von MyClass:

XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
<?xml version="1.0" encoding="utf-8"?>
<MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <publicString>Public String</publicString>
  <Test1>Teststring mit get/set-Methoden</Test1>
  <myClass2>
    <TestString>Eine public-Variable in Klasse MyClass2</TestString>
  </myClass2>
</MyClass>

Diese Serialisierung kann z.B. zur Speicherung von Daten oder zur Datenübertragung verwendet werden. Auch Konfigurationsdaten können leicht gespeichert, geladen und sogar ähnlich einer INI-Datei von Anwendern geändert werden. Nur sollte man dabei die Form der Datei möglichst nicht verändern.

Ich habe auch noch das Beispielprojekt angehängt (allerdings für Visual Studio 2005).


Anonymous - Mi 18.10.06 21:58

Sehr gut

Aber wie mache ich das wenn ich eine Verschachtelung in den Klassen habe (Composite)?

lg
E


UGrohne - Do 19.10.06 13:47

user profile iconAnonymous hat folgendes geschrieben:
Aber wie mache ich das wenn ich eine Verschachtelung in den Klassen habe (Composite)?

Steht doch in den Anmerkungen, auch diese werden mit serialisiert? Oder meinst Du etwas anderes?


paddy14 - Mo 04.07.11 16:51

Würde das auch mit gehen wenn die Eigenschaft ein Array wäre?


huuuuuh - Mo 04.07.11 17:09

eindimensionale Arrays und Listen gehen. bei zwei- und mehrdimensionalen funktioniert das nicht so problemlos...
was aber geht, ist, eine Liste zu serialisieren, die eindimensionale Arrays enthält. Also sowas: List<int[]> so kannst du zumindest zweidimensionale Arrays simulieren