• Decrease font size
  • Reset font size to default
  • Increase font size

/ads

/support

Wenn Ihr mich unterstützen möchtet, freue ich mich über eine Spende.
Das ist aber natürlich komplett freiwillig.
Konfigurationsdateien mit dem XMLSerializer
dev - c#
AddThis Social Bookmark Button

 

Jeder Entwickler ("Entwickler" nutze ich hier sowohl für weibliche als auch männliche Entwickler) kennt das leidige Thema Konfigurationsdateien. Viele Anwender vermutlich leider auch, aber das ist ein anderes Thema. Sobald ein Programm die Möglichkeit für die Auswahl verschiedener Einstellungen bietet, steht der Entwickler vor diversen Alternativen.

    1. Die Konfiguration wird überhaupt nicht gespeichert. Bei einem Neustart des Programms gehen alle Einstellungen in die ewigen, digitalen Jagdgründe ein. Soll sich doch der Benutzer erneut durch die bloß knapp 11 Dialoge hangeln.

    2. Die Konfiguration wird in einem proprietären Format z.B. einfache Serialisierung) gespeichert.

    3. Als Konfiguration wird eine möglichst einfache Struktur gespeichert, die ohne großen Aufwand schreib- und lesbar ist. Ein Beispiel hierfür wären z.B. Java-Properties-Dateien.

    4. Es wird XML wird. Zum Speichern/Lesen werden entweder ausgefuchste Mechanismen selbst implementiert oder bestehende Technologien wie z.B. JAXB verwendet.

      Punkt 1 ist meiner Meinung nach glücklicherweise auf dem Rückzug (kollektives Aufatmen von Millionen von Computerbenutzern).  Punkt 2 hat den Nachteil, dass es zum einen häufig schwierig ist, solche Dateien "mal eben" als Mensch zu verstehen. Zum anderen sind diese proprietären Dateien, nun ja, proprietär und damit häufig nicht wirklich austauschbar und wiederverwendbar.

      Ich kann wahrscheinlich kaum noch zählen, wie oft ich als Entwickler auf Java-Properties-Dateien zurückgegriffen habe. Sie sind sehr leicht les- und verstehbar. Die Entwicklung der Zugriffslogik ist ein Witz. Problem: diese Art von Konfigurationsdatei taugt nichts für komplexere Konfigurationen. Sobald hierarchische Daten in's Spiel kommen, wird es zappenduster, es sei denn man geht wirklich langwierige und schmutzige Wege.

      Für hierarchische Daten hingegen ist XML geradezu wie geschaffen. Problem hier: die Implementierung wirkt häufig etwas komplexer. Manchmal sind benötigte Hilfsklassen noch nicht einmal in der Standardklassenbibliothek zu finden.

      Dass XML-Serialisierung keine Hexenwerk sein muss, möchte ich anhand einiger Codeschnippsel am Bespiel von C# zeigen. Im .Net-Framework gibt es den ungemein nützlichen Namespace System.Xml.Serialization.

      Angenommen ich habe ein Programm, dass einen Webservice an verschiedenen URLs aufruft. Dieses Programm soll nun eine Liste dieser URLs speichern, dazu einen nutzerfreundlichen Anzeigenamen. Zuletzt benötigt es noch eine Kennzeichnung, welcher der Services als Standard ausgewählt ist.

      So ein Wertetupel  kann durch eine sehr simple Klasse repräsentiert werden.

      [Serializable()]  
      public class WebserviceConfigPair{
        private string url = null;
        private string displayName = null;
        private Boolean isDefault = false;
        public string Url{
         get { return url; }
         set { url = value; }
        }
        public string DisplayName{
         get { return displayName; }
         set { displayName = value; }
        }
       
        public Boolean IsDefault{
         get { return isDefault; }
         set { this.isDefault = value; }
        }
       
        public override String ToString() {
         return DisplayName;
        }

      So weit, so langweilig. Lediglich das Attribut [Serializable()] verdient eine Bemerkung. Hierdurch wird nämlich ausgesagt, dass diese Klasse komplett serialisierbar ist.Da eine Konfigurationsdatei aus vielen diese Werte bestehen kann, erstellen wir noch eine Klasse namens Configuration (heh, wer hat gesagt, dass man bei der Namensgebung kreativ sein muss).

      Diese sieht dann z.B. so aus:

      [Serializable()]  
      [XmlInclude(typeof(WebserviceConfigPair))]
      public class Configuration{
        private ArrayList wsPairList = new ArrayList();
        private ArrayList getWSPairList(){
         return this.wsPairList;
        }
        public void Add(WebserviceConfigPair pair){
         getWSPairList().Add(pair);
        }
        public WebserviceConfigPair[] GetConfigPairs(){
         if (getWSPairList().Count == 0){
           return null;
         }
         int count = getWSPairList().Count;
         WebserviceConfigPair[] pairs = new WebserviceConfigPair[count];
         for (int i = 0; i < count; i++){
           pairs[i]=(WebserviceConfigPair)getWSPairList()[i];
         }
         return pairs;
        }
        public ArrayList WSPairList{
         get { return wsPairList; }
         set { wsPairList = value; }
        }
        public void SaveConfig(String pathAndName){
         System.IO.FileStream outputStream =
              new FileStream(pathAndName, FileMode.Create);
         System.Xml.Serialization.XmlSerializer serializer =
              new XmlSerializer(this.GetType());
         serializer.Serialize(outputStream, this);
         outputStream.Close();
        }

      public static Configuration LoadConfig(String pathAndName){
        FileStream inputStream = null;
        Configuration config = null;
        try{
         XmlSerializer serializer =new XmlSerializer(typeof(Configuration));
         inputStream = new FileStream(pathAndName, FileMode.OpenOrCreate);
         FileInfo fileInfo=new FileInfo(pathAndName);
         if(fileInfo.Length==0) {
           inputStream.Close(); return null;
         }
         config = (Configuration)serializer.Deserialize(inputStream);
         inputStream.Close();
        }catch (Exception e){
          if(inputStream!=null) {
           inputStream.Close();
          }
          throw new Exception();
        }
        return config; }  
      }

      Interessant ist hier vor allem die Zeile [XmlInclude(typeof(WebserviceConfigPair))]. Diese besagt, dass beim Serialisieren/Deserialisieren mit hoher Wahrscheinlichkeit Typen der Klasse WebserviceConfigPair auftauchen. Dies war die Klasse, die wir zuerst angelegt hatten. Das ist sehr wichtig, ansonsten verschluckt sich der XMLSerializer beim Versuch die Daten zu schreiben/lesen. Die Methoden loadConfig und saveConfig zeigen, wie einfach die Implementierung ist.

      Das Schöne: wir haben keinerlei XML-bezogene Logik implementiert. Eigentlich wissen wir eher zufällig, dass hier überhaupt XML-Dateien geschrieben werden. Wir können uns aber davon überzeugen, wenn wir die geschriebene Datei öffnen.

      <?xml version="1.0"?>
      
      <Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <WSPairList>
          <anyType xsi:type="WebserviceConfigPair">
            <Url>http://meineUrl/dienstverzeichnis1</Url>
            <DisplayName>Mein Anzeigename</DisplayName>
            <IsDefault>true</IsDefault>
          </anyType>
          <anyType xsi:type="WebserviceConfigPair">
            <Url>http://meineUrl/dienstverzeichnis1</Url>
            <DisplayName>Mein Anzeigename2</DisplayName>
            <IsDefault>false</IsDefault>
          </anyType>
        </WSPairList>
      </Configuration>

      Sehr simpel, da das Beispiel natürlich auch nicht mit Komplexität protzt. Trotzdem ist dieser Weg sehr einfach erweiterbar. Das XML-File bleibt für Leser verständlich.
      Wie sieht das in Eurer favorisierten Programmiersprache aus? Geht es einfacher? Kennt Ihr noch mehr Möglichkeiten?

       

      Kommentar hinzufügen

      Ihr Name:
      Titel:
      Kommentar:
        Sicherheitscode zur Prüfung. Nur Kleinschreibung. Keine Leerzeichen.
      Sicherheitscode-Prüfung: