Objekte verschiedener Klassen als XML speichern

Wenn Sie in Ihrem Programm Objekte als XML-Datei speichern wollen, dann ist ein naheliegender Ansatz die Objekte einer Klasse in einer Datei zu speichern. Aber wenn Sie Objekte verschiedener Klassen haben, die untereinander in Beziehung stehen, was tun Sie dann? Im folgenden Beispiel sieht man einen Ausschnitt aus dem Klassendiagramm einer Termin- und Aufgabenverwaltung. Gemeinsame Eigenschaften von Termin und Aufgabe sind in der Klasse Ereignis enthalten. Objekte der Klasse Ereignis können auch eine Beziehung zu Objekten der Klasse Kategorie haben.

xml-objektgraph-speichern1

Variante 1: Verschiedene Dateien

Eine naheliegende Lösung wäre es, wenn Sie Aufgaben, Termine und Kategorien in getrennten Dateien speichern.

xml-objektgraph-speichern3

Dazu werden aus den Anwendungseinstellungen verschiedene Pfade gelesen und dann in verschiedene Dateien geschrieben. Bitte beachten Sie, dass Sie den StreamWriter für jede Datei neu mit dem entsprechenden Pfad initialisieren müssen. Beispielsweise so:

Public Sub speichern()   ' Listen in Xml speichern

'Deklaration der notwendigen Objekte Variablen für den Dateizugriff
Dim strDateipfadTermin As String 'Pfad zur Datei, aus der die Termine gelesen werden sollen
Dim strDateipfadAufgabe As String 'Pfad zur Datei, aus der die Aufgaben gelesen werden sollen
Dim strDateipfadKategorie As String 'Pfad zur Datei, aus der die Kategorien gelesen werden sollen

Dim objStreamWriter As StreamWriter 'wird zum Schreiben einer Datei benötigt
Dim objXmlSerializer As XmlSerializer 'wird zur Umwandlung von Objekten in XML-Daten benötigt

'Dateipfad aus den Anwendungseinstellungen lesen
'Dateipfad aus den Anwendungseinstellungen lesen
strDateipfadTermin = My.Settings.DatendateipfadTermin
strDateipfadAufgabe = My.Settings.DatendateipfadAufgabe
strDateipfadKategorie = My.Settings.DatendateipfadKategorie

'Schreibend auf die Datei für die Termine zugreifen
objStreamWriter = New StreamWriter(strDateipfadTermin)

'Objekte der Liste aller Termine in XML-Daten umwandeln und in die Datei schreiben
objXmlSerializer = New XmlSerializer(GetType(List(Of Termin)))
objXmlSerializer.Serialize(objStreamWriter, lstMeineTermine)

'Schreibend auf die Datei für die Aufgaben zugreifen
objStreamWriter = New StreamWriter(strDateipfadAufgabe)

'Objekte der Liste aller Aufgaben in XML-Daten umwandeln und in die Datei schreiben
objXmlSerializer = New XmlSerializer(GetType(List(Of Aufgabe)))
objXmlSerializer.Serialize(objStreamWriter, lstMeineAufgaben)

'Schreibend auf die Datei für die Kategorien zugreifen
objStreamWriter = New StreamWriter(strDateipfadKategorie)

'Objekte der Liste aller Kategorien in XML-Daten umwandeln und in die Datei schreiben
objXmlSerializer = New XmlSerializer(GetType(List(Of Kategorie)))
objXmlSerializer.Serialize(objStreamWriter, lstKategorienAlle)

'Dateizugriff beenden
objStreamWriter.Close()

End Sub

Quelle: Studierendenprojekt, anonymisiert

Das Lesen funktioniert dann analog, so dass Sie für jede Datei prüfen, ob sie existiert und ob Daten darin enthalten sind. (Wenn nicht, dann werden im folgenden Beispiel einige Beispieldaten geladen. Das hatten wir uns ja zu Übungszwecken so überlegt.)

Public Sub Laden()
'Deklaration der notwendigen Objekte Variablen für den Dateizugriff
Dim strDateipfadTermin As String 'Pfad zur Datei, aus der die Termine gelesen werden sollen
Dim strDateipfadAufgabe As String 'Pfad zur Datei, aus der die Aufgaben gelesen werden sollen
Dim strDateipfadKategorie As String 'Pfad zur Datei, aus der die Kategorien gelesen werden sollen

Dim objStreamReader As StreamReader 'Wird zum Lesen aus einer Datei benötigt
Dim objXmlSerializer As XmlSerializer 'Wird zur Umwandlung von XML-Daten in Objekte benötigt

'Dateipfad aus den Anwendungseinstellungen lesen
strDateipfadTermin = My.Settings.DatendateipfadTermin
strDateipfadAufgabe = My.Settings.DatendateipfadAufgabe
strDateipfadKategorie = My.Settings.DatendateipfadKategorie

'Termine

'lesend auf die Datei zugreifen
objStreamReader = New StreamReader(strDateipfadTermin)

'gelesene XML-Daten in Objekte umwandeln und die Liste der Benutzer füllen
objXmlSerializer = New XmlSerializer(GetType(List(Of Termin)))
lstMeineTermine = objXmlSerializer.Deserialize(objStreamReader)

'Dateizugriff beenden
objStreamReader.Close()

' Aufgaben

'lesend auf die Datei zugreifen
objStreamReader = New StreamReader(strDateipfadAufgabe)

'gelesene XML-Daten in Objekte umwandeln und die Liste der Benutzer füllen
objXmlSerializer = New XmlSerializer(GetType(List(Of Aufgabe)))
lstMeineAufgaben = objXmlSerializer.Deserialize(objStreamReader)

'Dateizugriff beenden
objStreamReader.Close()

' Kategorien

'lesend auf die Datei zugreifen
objStreamReader = New StreamReader(strDateipfadKategorie)

'gelesene XML-Daten in Objekte umwandeln und die Liste der Benutzer füllen
objXmlSerializer = New XmlSerializer(GetType(List(Of Kategorie)))
lstKategorienAlle = objXmlSerializer.Deserialize(objStreamReader)

'Dateizugriff beenden
objStreamReader.Close()

End Sub

Quelle: Studierendenprojekt, anonymisiert

Variante 2: Gemeinsames Container-Objekt

Die zweite Variante ist, dass Sie alle Objekte in einem gemeinsamen Container-Objekt zusammenfassen. Dieses Container-Objekt dient nur zum Speichern und Laden und hat sonst keine Entsprechung im Anwendungsbereich. Dann könnte das Klassendiagramm etwa so aussehen:

xml-objektgraph-speichern2

Aufgabe des Containers ist es, die vorhandenen getrennten Listen zu übernehmen und in eigenen Attributen abzulegen. Dann kann man den Container bequem als XML-Datei speichern. Das Laden ist dann auch vergleichsweise einfach. Hier zunächst die Implementierung der Contrainer-Klasse:

Public Class DatenContainer

  Private mlstAufgaben As List(Of Aufgabe)
  Private mlstTermine As List(Of Termin)
  Private mlstKategorienAlle As List(Of Kategorie)

  Public Sub New()
    mlstAufgaben = New List(Of Aufgabe)
    mlstTermine = New List(Of Termin)
    mlstKategorienAlle = New List(Of Kategorie)
  End Sub

  Public Sub New(plstAufgaben As List(Of Aufgabe), plstTermine As List(Of Termin), plstKategorienAlle As List(Of Kategorie))
    mlstAufgaben = plstAufgaben
    mlstTermine = plstTermine
    mlstKategorienAlle = plstKategorienAlle
  End Sub

  Public ReadOnly Property Aufgaben As List(Of Aufgabe)
    Get
      Return mlstAufgaben
    End Get
  End Property

  Public ReadOnly Property Termine As List(Of Termin)
    Get
      Return mlstTermine
    End Get
  End Property

  Public ReadOnly Property KategorienAlle As List(Of Kategorie)
    Get
      Return mlstKategorienAlle
    End Get
  End Property

End Class

Im Folgenden das Speichern des Containers in einer Datei. Die Datei umfasst dann jeweils alle Daten, weil der Container die Listen mit den verschiedenen Objekten zusammenfasst.

Public Sub speichern()   ' Listen in Xml speichern 

  'Deklaration der notwendigen Objekte Variablen für den Dateizugriff
  Dim strDateipfad As String 'Pfad zur Datei, aus der ALLE OBJEKTE gelesen werden sollen

  Dim objStreamWriter As StreamWriter 'wird zum Schreiben einer Datei benötigt
  Dim objXmlSerializer As XmlSerializer 'wird zur Umwandlung von Objekten in XML-Daten benötigt

  'Containerobjekt erzeugen und befüllen
  Dim container As DatenContainer = New DatenContainer(lstMeineAufgaben, lstMeineTermine, lstKategorienAlle)

  'Dateipfad aus den Anwendungseinstellungen lesen
  strDateipfad = My.Settings.Datendateipfad

  'Schreibend auf die Datei zugreifen
  objStreamWriter = New StreamWriter(strDateipfad)

  'Containerobjekt mit lallen enthaltenen Listen in XML-Daten umwandeln und in die Datei schreiben
  objXmlSerializer = New XmlSerializer(GetType(DatenContainer))
  objXmlSerializer.Serialize(objStreamWriter, container)

  'Dateizugriff beenden
  objStreamWriter.Close()

End Sub

Das Laden aus der Datei funktioniert dann analog:

Public Sub Laden()
  'Deklaration der notwendigen Objekte Variablen für den Dateizugriff
  Dim strDateipfad As String 'Pfad zur Datei, aus der die Termine gelesen werden sollen

  Dim objStreamReader As StreamReader 'Wird zum Lesen aus einer Datei benötigt
  Dim objXmlSerializer As XmlSerializer 'Wird zur Umwandlung von XML-Daten in Objekte benötigt
  Dim container As DatenContainer  ' Container für alle Daten der Anwendung

  'Dateipfad aus den Anwendungseinstellungen lesen
  strDateipfad = My.Settings.Datendateipfad

  'lesend auf die Datei zugreifen
  objStreamReader = New StreamReader(strDateipfad)

  'gelesene XML-Daten in Objekte umwandeln und die Liste der Benutzer füllen
  objXmlSerializer = New XmlSerializer(GetType(DatenContainer))
  container = objXmlSerializer.Deserialize(objStreamReader)

  ' Listen aus Container füllen
  lstMeineAufgaben = container.Aufgaben
  lstMeineTermine = container.Termine
  lstKategorienAlle = container.KategorienAlle

  'Dateizugriff beenden
  objStreamReader.Close()

End Sub

Vielleicht fanden Sie diese Überlegungen hilfreich. Wenn ja, dann weiterhin viel Spaß!

Schreibe einen Kommentar