Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
XML-Serialisieren/Deserialisieren für IsolatedStorage verdoppelt items in einer Liste
UHM
myCSharp.de - Member



Dabei seit:
Beiträge: 19

Themenstarter:

XML-Serialisieren/Deserialisieren für IsolatedStorage verdoppelt items in einer Liste

beantworten | zitieren | melden

Hallo,

ich habe eine abgeleitete serialisierbare Klasse zum Speichern der Benutzterdaten im Isolated Storage. Dabei ist eine Liste mit Dateinamen in der Basisklasse, die in einer DLL ist. Leider verdoppelt sich die Liste jedes Mal beim serialisieren und wieder deserialisieren. Auszüge aus der Klasse sind dabei:


  [Serializable]
  public class UserData
  {
    public List<String> strlOtherFilename;

    public List<String> OtherFilenames
    {
      get { return strlOtherFilename; }
    }

    public UserData()
    {
      strlOtherFilename = new List<string>();
      ....
    }
  }

  [Serializable]
  public class AppUserData:UserData
  {
    // hier ist in der ganzen abgeleiteten Klasse nichts mit den Dateinamen
    ...
    public AppUserData()
    {
       ...
    }
  }

  public partial class DrawingApp : Form, IMessageFilter
  {
    protected UserData Benutzerdaten;

   ...

    virtual protected void AppSaveUserData(XmlSerializer xs, IsolatedStorageFileStream userData)
    {
      if (null == xs)
      {
        xs = new XmlSerializer(typeof(UserData));
      }
      xs.Serialize(userData, Benutzerdaten);
    }

    virtual protected void AppLoadUserData(XmlSerializer xs, StreamReader sr)
    {
      if (null == xs)
      {
        xs = new XmlSerializer(typeof(UserData));
      }
      Benutzerdaten = (UserData)xs.Deserialize(sr);
    }

    virtual protected void DrawingApp_Load(object sender, EventArgs e)
    {
      try
      {
        using (IsolatedStorageFileStream userData = new IsolatedStorageFileStream(GetUserDataStorageName(), FileMode.Open))
        {
          if (null != userData)
          {
            using (StreamReader sr = new StreamReader(userData))
            {
              AppLoadUserData(null, sr);
            }
            ...
          }
        }
      }
      catch
      {
        Benutzerdaten = new UserData();
      }
      ...
  }

    override protected void AppLoadUserData(XmlSerializer xs, StreamReader sr)
    {
      if (null == xs)
      {
        xs = new XmlSerializer(typeof(AppUserData));
      }
      audBenutzerdaten = (AppUserData)xs.Deserialize(sr);
      SetUserData(audBenutzerdaten);

    }

  public partial class MainApp : DLL.DrawingApp
  {
    protected AppUserData audBenutzerdaten;

    ...

    override protected void AppSaveUserData(XmlSerializer xs, IsolatedStorageFileStream userData)
    {
      ...
      if (null == xs)
      {
        xs = new XmlSerializer(typeof(AppUserData));
      }
      FileStream fs = new FileStream("Test.txt", FileMode.Create);
      xs.Serialize(fs, (AppUserData)audBenutzerdaten);   // Testausgabe in Datei
      xs.Serialize(userData, (AppUserData)audBenutzerdaten);
   }

    override protected void DrawingApp_Load(object sender, EventArgs e)  // Event Form.Load
    {
      base.DrawingApp_Load(sender, e);
      ...
    }

Benutzerdaten und audBenutzerdaten sind zwar auf dem ersten Blick 2 verschiedene Objekte, werden aber immer gleichgesetzt gehalten (Benutzerdaten = audBenutzerdaten).
In der zum Test ausgegebenen Datei, die wie ich hoffe dann identisch mit dem Isolated Storage ist, steht dann:


<?xml version="1.0"?>
<RvmConfigUserData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <strlOtherFilename>
    <string>C:\...\Test.tst</string>
  </strlOtherFilename>
  ...
  <OtherFilenames>
    <string>C:\...\Test.tst</string>
  </OtherFilenames>
  ...
</AppUserData>

Für mich ist dabei etwas verwunderlich, daß dann da <OtherFilenames> mit enthalten ist, das ist ja nur ein Zugriffskonstrukt. Sollte aber eigentlich nichts bewirken, da <OtherFilenames> ja nur get besitzt und kein set.
Oder interpretiere ich da etwas falsch?

Gruß
UHM
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16112

beantworten | zitieren | melden


  public List<String> strlOtherFilename;

  public List<String> OtherFilenames
  {
    get { return strlOtherFilename; }
  }

Damit hast Du eine Eigenschaft mit einem expliziten Feld erzeugt. Aber:
- Felder sollten (ausser in ein paar Ausnahmen) immer private sein
- Das Feld ist unnötig, Dir reicht ein get mit einem hidden field => public List<String> OtherFilenames {get;}

Dadurch, dass Du das Feld public hast, beachtet der Serializer das Feld beim Serialisieren.
Das ist Dein Fehler, und durch das doppelte Serialisieren des Inhalts haste Dein Ergebnis.
Siehe dazu die Basics in https://docs.microsoft.com/de-de/dotnet/api/system.xml.serialization.xmlserializer?view=net-5.0

Ansonsten noch Feedback an den Code:
- Du disposed die Handles nicht, zB bei den Streams -> kann zu Memory Leaks / Memory Exceptions führen
- Kannst Dir die ganze Arbeit fast vollständig sparen, wenn Du System.Text.Json verwendest, das zudem viel performanter und schlanker ist.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
T-Virus
myCSharp.de - Member



Dabei seit:
Beiträge: 1894
Herkunft: Nordhausen, Nörten-Hardenberg

beantworten | zitieren | melden

Ist ein einfacher Fehler.
strlOtherFilename ist als public deklariert, entsprechend wird die Liste einmal durch das public Feld und durch OtherFilenames serailisiert.
In deinem Fall sollte auch eine einfache Auto Property reichen, dann hast du den Fehler nicht.

Nachtrag:
Abt war schneller
Falls möglich steig auf Json um.
Wenn ihr größere Listen/Objekte fahrt, wird Xml schnell zum Overhead.

T-Virus
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von T-Virus am .
Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
private Nachricht | Beiträge des Benutzers
UHM
myCSharp.de - Member



Dabei seit:
Beiträge: 19

Themenstarter:

beantworten | zitieren | melden

Läuft, besten Dank und schönen Abend noch.
private Nachricht | Beiträge des Benutzers