Allgemein
- im Beispiel wird ein Objekt mit seinen Unterobjekten als XML serialisiert und als Datei ObjektListe.xml gespeichert
- Wichtig ist immer die Angabe der Standardkonstruktoren in allen Klassen, sonst werden Exceptions geworfen!
- alle zu speichernden Elemente müssen public sein
- Falls Objektreferenzen als public-Variablen verwendet werden, dann sollte man darauf achten, dass keine zirkulären Bezüge auftreten! Ggf. sollte man diese Variablen mit [XmlIgnore] überspringen.
- ArrayList, List<T> (generische Listen) und ReadOnly-Properties werden nicht serialisiert!
- Wichtig ist außerdem, dass nicht alle Elemente, z.B. Referenz-Variablen vom Typ “object”, als [XmlAttribute(“Name”)] definiert werden können. Die XMLTags müssen dann häufig in [XmlElement(“Name”)] umgeändert werden.
Beispielcode
using System.IO;
using System.Xml;
using System.Xml.Serialization;
// ein Enumerator, zur Demonstration
public enum ObjektTyp
{
Viereck, // wird später als "Viereck" gespeichert
[XmlEnum("D")]
Dreieck, // wird später als "D" gespeichert
[XmlEnum("Q")]
Quadrat // wird später als "Q" gespeichert
}
// Basisobjekt zur Demonstration der Speicherung
// der Basis-Eigenschaften, importiert das abgeleitete
// Objekt "Objekt"
[XmlInclude(typeof(Objekt))]
public class BasisObjekt
{
// Unterelement string
[XmlElement("Name")]
public string sName = "n/a";
// Standardkonstruktor
public BasisObjekt()
{
}
}
// Listenobjekt was innerhalb von ObjektListe verwaltet wird
// ist von BasisObjekt abgeleitet
public class Objekt : BasisObjekt
{
// ein Beispiel-Attribut von Objekt
[XmlAttribute("id")]
public int iId;
// private -> wird nicht gespeichert
private float _a;
// float-Property, wird erst nach allen lokalen public-Variablen gespeichert,
// obwohl es von der Reihenfolge her vor _b kommen müsste
[XmlElement]
public float a
{
get
{
return _a;
}
set
{
_a = value;
}
}
// float-Unterelement
[XmlElement("b")]
public float _b;
// Enumerator-Unterelement
[XmlElement("Typ")]
public ObjektTyp otTyp;
// ein ParameterArray mit 3 int-Parametern definieren
[XmlArray("ParameterListe")]
[XmlArrayItem("Parameter")]
public int[] Params = new int[3];
// Standardkonstruktor mit Aufruf des Konstruktors der Basisklasse
public Objekt()
: base()
{
}
public Objekt(float fa, float fb, int iObjektId, ObjektTyp Typ)
{
_a = fa;
_b = fb;
iId = iObjektId;
otTyp = Typ;
}
// kleine Ausgabefunktion zur Kontrolle der Objektvariablen nach dem Lesen
public void Print()
{
Console.WriteLine(sName + "[" + otTyp.ToString() + "]");
Console.WriteLine("ID: {0}", iId);
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Parameter {0}: {1}", i, Params[i]);
}
Console.WriteLine("{0} x {1} = {2}", _a, _b, _a * _b);
}
}
// Rootobjekt [XmlRoot], das geladen und gespeichert werden soll
[XmlRoot("Objektliste")]
public class ObjektListe
{
// ein String
[XmlElement("Name")]
public string _sListenName;
// dieses Element wird bei der Serialisierung ignoriert
[XmlIgnore]
public int _iID;
// ein dynamisches List-Array mit Objekten definieren
[XmlArray("Objekte")]
[XmlArrayItem("Objekt")]
public List<Objekt> Objekte = new List<Objekt>();
// Standardkonstruktor
public ObjektListe()
{
}
public ObjektListe(string sListenName, int iID)
{
_sListenName = sListenName;
_iID = iID;
}
}
// Objekt serialisiert speichern
private void btnSave_Click(object sender, EventArgs e)
{
// Root-Objekt erstellen
ObjektListe ol = new ObjektListe("Flächen", 1);
// drei Listenelemente hinzufügen
ol.Objekte.Add(new Objekt(1.2f, 3.4f, 1, ObjektTyp.Dreieck));
ol.Objekte.Add(new Objekt(2.5f, 5.6f, 2, ObjektTyp.Viereck));
ol.Objekte.Add(new Objekt(4.7f, 8.1f, 3, ObjektTyp.Quadrat));
// Namen und Parameter des Listenelemente definieren
ol.Objekte[0].sName = "Fläche 1";
ol.Objekte[0].Params[0] = 1;
ol.Objekte[0].Params[1] = 2;
ol.Objekte[0].Params[2] = 3;
ol.Objekte[1].sName = "Fläche 2";
ol.Objekte[1].Params[0] = 4;
ol.Objekte[1].Params[1] = 5;
ol.Objekte[1].Params[2] = 6;
ol.Objekte[2].sName = "Fläche 3";
ol.Objekte[2].Params[0] = 7;
ol.Objekte[2].Params[1] = 8;
ol.Objekte[2].Params[2] = 9;
// Stream öffnen
FileStream fs = new FileStream("c:\\ObjektListe.xml", FileMode.Create);
// Objekte als XML serialisieren
XmlSerializer xs = new XmlSerializer(typeof(ObjektListe));
xs.Serialize(fs, ol);
// Stream schließen
fs.Flush();
fs.Close();
}
// Objekt laden und deserialisieren
private void btnLoad_Click(object sender, EventArgs e)
{
// Stream öffnen
FileStream fs = new FileStream("c:\\ObjektListe.xml", FileMode.Open);
// Objekt deserialisieren
XmlSerializer xs = new XmlSerializer(typeof(ObjektListe));
Object o = xs.Deserialize(fs);
ObjektListe ol = o as ObjektListe;
// wenn die Deserialisierung funktioniert hat
// Testdaten ausgeben (Print())
if (ol != null)
{
for (int i = 0; i < ol.Objekte.Count; i++)
{
Objekt obj = ol.Objekte[i];
if (obj != null)
{
obj.Print();
}
}
}
// Stream schließen
fs.Close();
}
- die gespeicherte Ausgabedatei ObjektListe.xml sieht wie folgt aus:
<?xml version="1.0"?>
<Objektliste xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>Flächen</Name>
<Objekte>
<Objekt id="1">
<Name>Fläche 1</Name>
<b>3.4</b>
<Typ>D</Typ>
<ParameterListe>
<Parameter>1</Parameter>
<Parameter>2</Parameter>
<Parameter>3</Parameter>
</ParameterListe>
<a>1.2</a>
</Objekt>
<Objekt id="2">
<Name>Fläche 2</Name>
<b>5.6</b>
<Typ>Viereck</Typ>
<ParameterListe>
<Parameter>4</Parameter>
<Parameter>5</Parameter>
<Parameter>6</Parameter>
</ParameterListe>
<a>2.5</a>
</Objekt>
<Objekt id="3">
<Name>Fläche 3</Name>
<b>8.1</b>
<Typ>Q</Typ>
<ParameterListe>
<Parameter>7</Parameter>
<Parameter>8</Parameter>
<Parameter>9</Parameter>
</ParameterListe>
<a>4.7</a>
</Objekt>
</Objekte>
</Objektliste>
- nach dem Zurücklesen sollte Folgendes auf der Konsole ausgegeben werden:
Fläche 1[Dreieck]
ID: 1
Parameter 0: 1
Parameter 1: 2
Parameter 2: 3
1,2 x 3,4 = 4,08
Fläche 2[Viereck]
ID: 2
Parameter 0: 4
Parameter 1: 5
Parameter 2: 6
2,5 x 5,6 = 14
Fläche 3[Quadrat]
ID: 3
Parameter 0: 7
Parameter 1: 8
Parameter 2: 9
4,7 x 8,1 = 38,07
- weiterführender Link: Link