Datenaustausch mit XML / Objekt-Serialisierung mit C#.NET

Objekt-Serialisierung mit C#.NET

Objekt-Serialisierung mit C#.NET

Wie in anderen Programmiersprachen, können XML Dokumente auch in C#.NET durch Serialisierung von Objekten bzw. Objektlisten erzeugt werden.

Objekt-Serialisierung mit C#.NET

pic/Csharp_Objektserialisierung.png

Dieses Verfahren erlaubt analog auch die Deserialisierung von XML in C#.NET-Objekte.

Als Beispiel dient uns die C#.NET-Klasse "Mensch".


namespace CSharpSchulung
{
 [Serializable]
 public class Mensch 
 {
  #region privateFields
  /// <summary>private geschütztes Feld _Vorname</summary>
  private String _Vorname;
  /// <summary>private geschütztes Feld _Nachname</summary>
  private String _Nachname;
  /// <summary>private geschütztes Feld _Alter</summary>
  private int _Alter;
  #endregion
  /// <summary>Schreibmethode für _Alter</summary>
  /// <param name="a">wird auf _Alter kopiert</param>
  public void SetAlter(int a)
  {
   _Alter = Math.Abs(a);
  }
  /// <summary>Lesemethode (GET) für _Alter</summary>
  /// <returns>_Alter</returns>
  public int GetAlter() // Function
  {
   return _Alter;
  }
  #region Properties
  /// <summary>Kombinierte Lese- und 
  /// Schreibmethode für _Alter</summary>
  public int Alter
  {
   set 
   {    
    _Alter = Math.Abs( value);
   }
   get 
   {
    return _Alter;
   }
  }
  /// <summary>Kombinierte Lese- und 
  /// Schreibmethode für _Vorname</summary>
  public String Vorname
  {
   set
   {
    this._Vorname = value.ToUpper();
   }
   get
   {
    return this._Vorname;
   }
  }
  /// <summary>Kombinierte Lese- und 
  /// Schreibmethode für _Nachname</summary>
  public String Nachname
  {
   set
   {
    this._Nachname = value.ToUpper();
   }
   get
   {
    return this._Nachname;
   }
  }
  #endregion
  #region Konstruktoren
  /// <summary>Standardkonstruktor 
  /// der Klasse Mensch</summary>
  public Mensch()
  {
  }
  /// <summary>Parametrisierter Konstruktor der Klasse Mensch</summary>
  /// <param name="vn">wird via Property _Vorname zugewiesen</param>
  /// <param name="nn">wird via Property _Nachname zugewiesen</param>
  /// <param name="a">wird via Property _Alter zugewiesen</param>
  public Mensch(String vn, String nn, int a)
  {
   this.Vorname = vn;
   this.Nachname = nn;
   this.Alter = a;
  }
  #endregion
  #region Methoden
  /// <summary>Überschriebene ToString()-Methode</summary>
  /// <returns>Vorname Nachname ist Alter Jahre alt</returns>
  public override String ToString()
  {
   return String.Format("{0} {1} ist {2} Jahre alt", 
         Vorname, Nachname, Alter);
  }
  #endregion
 }
}

Von dieser C#.NET-Klasse werden mehrere Objekte erzeugt und in eine generische Liste, die ausschließlich Objekte der C#.NET-Klasse "Mensch" akzeptiert, eingefügt. Durch "value.ToUpper()" in den Properties wird jede String-Einzelinformation in Großbuchstaben umgewandelt.

Anschließend soll die gesamte Liste (mit allen Mensch-Objekten darin) in ein XML-Dokument serialisiert werden. Dies geschieht sehr einfach mit den C#.NET-Klassen XmlSerializer und XmlWriter:


  public static List<Mensch> menschen = new List<Mensch>();
  public static void InitList()
  {
    menschen.Add(new Mensch("Simone", "Sinnlos", 34));
    menschen.Add(new Mensch("Horst", "Hilflos", 44));
    menschen.Add(new Mensch("Werner", "Witzlos", 33));
    menschen.Add(new Mensch("Lotte", "Rielos", 33));
    menschen.Add(new Mensch("Siggi", "Sorglos", 44));
  }
  static void Genericdemo()
  {
   InitList();  
   try
   {
    XmlSerializer ser = new XmlSerializer(typeof(List<Mensch>));
    XmlWriter w  = XmlWriter.Create(@"C:\menschen.xml");
    ser.Serialize(w, menschen);
   }
   catch(Exception exc)
   {
    Console.WriteLine(exc.StackTrace);
   }
  }

Die XmlSerializer-Serialisierung generiert in C#.NET das folgende XML-Dokument:


<?xml version="1.0" encoding="utf-8"?>
<ArrayOfMensch 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <Mensch>
  <Alter>34</Alter>
  <Vorname>SIMONE</Vorname>
  <Nachname>SINNLOS</Nachname>
 </Mensch>
 <Mensch>
  <Alter>44</Alter>
  <Vorname>HORST</Vorname>
  <Nachname>HILFLOS</Nachname>
 </Mensch>
 <Mensch>
  <Alter>33</Alter>
  <Vorname>WERNER</Vorname>
  <Nachname>WITZLOS</Nachname>
 </Mensch>
 <Mensch>
  <Alter>33</Alter>
  <Vorname>LOTTE</Vorname>
  <Nachname>RIELOS</Nachname>
 </Mensch>
 <Mensch>
  <Alter>44</Alter>
  <Vorname>SIGGI</Vorname>
  <Nachname>SORGLOS</Nachname>
 </Mensch>
</ArrayOfMensch>

Umgekehrt wird im C#.NET-Deserialisierungs-Prozeß dieselbe Datei wieder in eine generische Liste konvertiert:


    static void Deserialize()
    {
      XmlSerializer ser;
      ser   = new XmlSerializer(typeof(List<Mensch>));
      List<Mensch> menschen = null;
      using (FileStream 
              fs = new FileStream(@"C:\menschen.xml", 
                                  FileMode.Open))
      {
        menschen = (List<Mensch>) ser.Deserialize(fs);
      }
      foreach (Mensch m in menschen)
      {
        Console.WriteLine(m);
      }
    }

Arbeiten mit Xml.Serialization

Im .NET Framework gibt es die Möglichkeit zu einer attributorientierten Programmierung. Damit sind keine XML-Attribute gemeint, sondern die Möglichkeiten der abstrakten Attribute-Klasse, die die Grundlage für sehr brauchbare Klassen im Namespace "System.Xml.Serialization" darstellt.

Durch zusätzliche Verwendung der attributorientierten Programmierung in C#.NET ist es möglich, den Aufbau des XML-Serialisierungsdokuments zu beeinflussen.


 [Serializable]
 public class Mensch 
 {
   [System.Xml.Serialization.XmlAttribute("AGE")]
   public int Alter { set; get; }
   [System.Xml.Serialization.XmlElement("FIRSTNAME")]
   public String Vorname { set; get; }
   ...
  }
 [Serializable]
 [System.Xml.Serialization.XmlRoot("myROOT")]
 [System.Xml.Serialization.XmlInclude(typeof(Mensch))]
 public class ListeMenschen
 {
   [System.Xml.Serialization.XmlArray("Personen")]
   [System.Xml.Serialization.XmlArrayItem("MENSCH")]
   public List<Mensch> mm = new List<Mensch>();
 }

Das generierte XML Dokument sieht dann so aus:


<myROOT 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Personen>
    ...
    <MENSCH AGE="37">
      <FIRSTNAME>SIGGI</FIRSTNAME>
      <LASTNAME>SORGLOS</LASTNAME>
    </MENSCH>
  </Personen>
</myROOT>

Arbeiten mit WebServices

Die Klasse "Mensch" läßt sich auch für die Erstellung eines Webservice verwenden. Unter einem kann man sich eine Client-Server-Anwendung vorstellen, wobei der Client eine Anfrage (Request) an einen Server sendet und von diesem eine Antwort (Response) erhält. Dabei kann sowohl mit SOAP als auch mit HTTP POST gearbeitet werden.

Bei einem Webservice besteht der Response aus XML, für das eine umfangreiche WebServiceDescription zur Verfügung steht. Die WebServiceDescription ist ihrerseits abgefaßt in einer WebServiceDescriptionLanguage (WSDL: ebenfalls XML).

pic/Webservice.jpg

Dank der ausgereiften Systemunterstützung im VisualStudio ist die serverseitige C#.NET-Logik recht übersichtlich. Hier habe ich einen WebService mit zwei Methoden "getMensch" (mit einem String-Parameter) sowie "getMenschen()" erstellt.


using System;
using System.Collections.Generic;
using System.Web.Services;
namespace WebApplication3
{
  [WebService(Namespace = "http://wilfried-grupe.de/webservice")]
  [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  [System.ComponentModel.ToolboxItem(false)]
  public class WebService1 : System.Web.Services.WebService
  {
    [WebMethod]
    public Mensch getMensch(String NN)
    {
      Mensch.initList();
      Mensch m = null;      
      for (int i = 0; i < Mensch.menschen.Count; i++)
      {
        Mensch mm = Mensch.menschen[i];
        if (mm.Nachname == NN.ToUpper()) m = mm;
      }
      return m;
    }
    [WebMethod]
    public List<Mensch> getMenschen()
    {
      Mensch.initList();
      return Mensch.menschen;
    }
  }
}

"getMensch" liest aus der bereits bekannten Liste jenes Objekt heraus, dessen Property "Nachname" identisch ist mit dem übergebenen Parameter "NN". Ein Formular erlaubt, den Vorgang mit dem HTTP POST-Protokoll zu testen.

pic/Webservice2.jpg

Der Response an den Empfänger ist einfach:


<?xml version="1.0" encoding="UTF-8"?>
<Mensch 
  xmlns="http://wilfried-grupe.de/webservice" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Alter>34</Alter>
  <Vorname>SIMONE</Vorname>
  <Nachname>SINNLOS</Nachname>
</Mensch>

Das ist aber nicht alles: ergänzend liefert die WebserviceDescription noch eine umfangreiche Beschreibung, von der ich hier nur einen Teil ("wsdl:types") dessen darstellen möchte, der sich auf "getMensch" bezieht. Dabei steht der Namespace-Präfix "s" für XML Schema (xmlns:s="http://www.w3.org/2001/XMLSchema"). Ein WebClient ist in der Lage, sich auf der Basis dieser Informationen leistungsfähige Klassen automatisch zu generieren, die in der Lage sind, das erhaltene XML zu verarbeiten.


<s:element name="getMensch">
  <s:complexType>
    <s:sequence>
      <s:element name="NN" 
                 type="s:string" 
                 maxOccurs="1" 
                 minOccurs="0"/>
    </s:sequence>
  </s:complexType>
</s:element>
<s:element name="getMenschResponse">
  <s:complexType>
    <s:sequence>
      <s:element name="getMenschResult" 
                 type="tns:Mensch" 
                 maxOccurs="1" 
                 minOccurs="0"/>
    </s:sequence>
  </s:complexType>
</s:element>
<s:complexType name="Mensch">
  <s:sequence>
    <s:element name="Alter" 
               type="s:int" 
               maxOccurs="1" 
               minOccurs="1"/>
    <s:element name="Vorname" 
               type="s:string" 
               maxOccurs="1" 
               minOccurs="0"/>
    <s:element name="Nachname" 
               type="s:string" 
               maxOccurs="1" 
               minOccurs="0"/>
  </s:sequence>
</s:complexType>

Die zweite WebMethod "getMenschen()" liefert die gesamte Liste zurück. Selbstverständlich liefert uns die WebServiceDescription auch für s:element name="getMenschen" und "getMenschenResponse" sowie für s:complexType name="ArrayOfMensch" aussagekräftige Definitionen zurück.


<?xml version="1.0" encoding="utf-8"?>
<ArrayOfMensch
  xmlns="http://wilfried-grupe.de/webservice"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Mensch>
    <Alter>34</Alter>
    <Vorname>SIMONE</Vorname>
    <Nachname>SINNLOS</Nachname>
  </Mensch>
  <Mensch>
    <Alter>44</Alter>
    <Vorname>HORST</Vorname>
    <Nachname>HILFLOS</Nachname>
  </Mensch>
  <Mensch>
    <Alter>33</Alter>
    <Vorname>WERNER</Vorname>
    <Nachname>WITZLOS</Nachname>
  </Mensch>
  <Mensch>
    <Alter>33</Alter>
    <Vorname>LOTTE</Vorname>
    <Nachname>RIELOS</Nachname>
  </Mensch>
  <Mensch>
    <Alter>44</Alter>
    <Vorname>SIGGI</Vorname>
    <Nachname>SORGLOS</Nachname>
  </Mensch>
</ArrayOfMensch>

wg / 4. Januar 2018



Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf:

Vorname
Nachname
Mailadresse







Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

Mobil: 0151. 750 360 61 * eMail: info2018@wilfried-grupe.de

www.wilfried-grupe.de/Objektserialisierung_csharp.html