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 Serialisierung: List<string> wird nicht deserialisiert
fortuneNext
myCSharp.de - Member



Dabei seit:
Beiträge: 45
Herkunft: Aachen

Themenstarter:

XML Serialisierung: List<string> wird nicht deserialisiert

beantworten | zitieren | melden

verwendetes Datenbanksystem: <XML>

Hallo,
ich bin es gleich nochmal.

Ich habe ein Problem mit dem Deserialisieren einer sich in einem Objekt befindlichen List<string>.

Meine Klasse XmlStrucutralAccount enthält eine List<string>. Ich möchte sie mit einem XmlSerializer serialisieren. Folgende Datei ist die Ausgabe meines Beispielsets:


<?xml version="1.0"?>
<ArrayOfXmlAccount xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <XmlAccount xsi:type="XmlValueAccount">
    <Name>AktivKonto</Name>
    <AccountType>Active</AccountType>
    <StartValue>150</StartValue>
  </XmlAccount>
  <XmlAccount xsi:type="XmlValueAccount">
    <Name>PassivKonto</Name>
    <AccountType>Passive</AccountType>
    <StartValue>-15</StartValue>
  </XmlAccount>
  <XmlAccount xsi:type="XmlUserAccount">
    <Name>User</Name>
    <AccountType>User</AccountType>
    <StartValue>0</StartValue>
    <Email>test@mail.de</Email>
  </XmlAccount>
  <XmlAccount xsi:type="XmlStructuralAccount">
    <Name>Strukturkonto</Name>
    <AccountType>Active</AccountType>
    <subaccounts>
      <string>AktivKonto</string>
      <string>PassivKonto</string>
      <string>User</string>
    </subaccounts>
  </XmlAccount>
</ArrayOfXmlAccount>

Dabei kann man unter dem 4. Punkt sehen, dass die Liste <subaccounts> korrekt serialisiert wird.
Beim Deserialisieren bleibt die Liste "subaccounts" jedoch leer! Alles andere wird absolut korrekt eingelesen. Was könnte ich falsch gemacht haben?

Weitere Informationen: XmlStructuralAccount ist eine Unterklasse von XmlAccount (abstract), ebenso XmlValueAccount. XmlUserAccount ist wiederum eine Unterklasse von XmlValueAccount. Ich habe jeweils [XmlInclude(typeof(*Unterklasse(n)*)] vor die Klassen gesetzt, weitere [] Attribute habe ich nicht gesetzt.
Kommandos, die ich benutze:

XmlSerializer serializer = new XmlSerializer(typeof(List<XmlAccount>)); // zum schreiben
List<XmlAccount> xmlAccounts = (List<XmlAccount>)serializer.Deserialize(streamReader); // zum lesen
Insgesamt handelt es sich also um eine List<Account>, die serialisiert werden soll.

Ich habe die Vermutung, dass ich vielleicht irgendwelche Attribute fehlen? Aber warum wird die Datei dann korrekt geschrieben, jedoch nicht gelesen?

Vielleicht hat ja jemand eine Idee. :-)
Freundliche Grüße
fortuneNext
Dieser Beitrag wurde 4 mal editiert, zum letzten Mal von fortuneNext am .
private Nachricht | Beiträge des Benutzers
MrSparkle
myCSharp.de - Team

Avatar #avatar-2159.gif


Dabei seit:
Beiträge: 5.655
Herkunft: Leipzig

beantworten | zitieren | melden

Hi fortuneNext,
Zitat von fortuneNext
Beim Deserialisieren bleibt die Liste "subaccounts" jedoch leer! Alles andere wird absolut korrekt eingelesen. Was könnte ich falsch gemacht haben?

Wie soll da jemand etwas dazu sagen, ohne die XmlAccount-Klasse zu kennen?
Bitte beachte [Hinweis] Wie poste ich richtig?, Punkt 5.

Christian
Weeks of programming can save you hours of planning
private Nachricht | Beiträge des Benutzers
Ruben
myCSharp.de - Member

Avatar #avatar-2971.jpg


Dabei seit:
Beiträge: 61
Herkunft: Hamburg

beantworten | zitieren | melden

Ich könnte hier zwei Aussagen zu machen:

1. Je nach Implementierung der Klasse, in der sich die Liste befindet, konnte diese nicht erfolgreich deserialisiert werden, weil dort etwas an Code vorhanden ist, was den Mechanismus zu deserialisieren beeinflusst.

Hier muss ich dem guten "MrSparkle" zustimmen.
Ohne weitere Informationen wird niemand imstande sein eine passende Lösung vorzuschlagen oder zumindest zu helfen, den richtigen Weg zu finden.

2. Ein Alternative wäre (ohne zu Wissen was in der Klasse implemtiert ist) auch mal den DataContractSerializer auszuprobieren.
Der kann auch Objekte nach XML serialisieren und umgekehrt.
Auseinandersetzen kannst man sich damit auf dieser Seite:
DataContractSerializer-Klasse
In der Zeit vor fünf Minuten ist Jetzt die Zukunft. Jetzt ist die Gegenwart. Die Zeit, in der ich zu erzählen begonnen habe, ist die Vergangenheit von Jetzt und die Zukunft von der Gegenwart der Zeit, fünf Minuten bevor ich zu erzählen begann.
private Nachricht | Beiträge des Benutzers
fortuneNext
myCSharp.de - Member



Dabei seit:
Beiträge: 45
Herkunft: Aachen

Themenstarter:

beantworten | zitieren | melden

Hi,

Entschuldigung, das wäre natürlich sinnvoll gewesen! Da die Klassen recht trivial sind, hatte ich das fälschlicherweise als irrelevant angenommen. Mein Fehler.

Hier die beiden Definitionen:

[XmlInclude(typeof(XmlStructuralAccount)), XmlInclude(typeof(XmlValueAccount))]
    public abstract class XmlAccount
    {
        public string Name { get; set; }

        public AccountTypes AccountType { get; set; }
    }

[XmlInclude(typeof(List<String>))] // brauch ich das überhaupt? klappt ohne auch nicht
    public class XmlStructuralAccount : XmlAccount
    {
        public List<string> Subaccounts;

        public XmlStructuralAccount() { }

        public XmlStructuralAccount(StructuralAccount origin)
        {
            Name = origin.Name;
            AccountType = origin.AccountType;
            Subaccounts = new List<string>();
            foreach (Account account in origin.Subaccounts)
            {
                Subaccounts.Add(account.Name);
            }
        }
    }

Ich denke, die anderen beiden Klassen sind wirklich irrelevant.

Gruß
fortuneNext
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von fortuneNext am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16.306

beantworten | zitieren | melden

Ich mein Du brauchst die XML angaben per Attribute nicht, sondern musst dem Serializer die Typen mitgeben.

Sprich sowas wie

var typeList = new List<Type>( );
typeList.Add( typeof( XmlStructuralAccount  ) );

var xmlSerializer = new XmlSerializer( typeof( XmlAccount ), typeList.ToArray( ) );
bzw. könnte auch typeof ( XmlAccount [] ) sein.
private Nachricht | Beiträge des Benutzers
fortuneNext
myCSharp.de - Member



Dabei seit:
Beiträge: 45
Herkunft: Aachen

Themenstarter:

beantworten | zitieren | melden

Hi,

kann es grade nicht ausprobieren, werde ich morgen tun.
Allerdings frage ich mich, warum er dann die Datei korrekt schreibt und nur beim Lesen ausgerechnet nur dieses eine Feld leer bleibt, alle anderen aber wunderbar funktionieren?
(Die Attribute hab ich übrigens eingefügt, weil der Compiler mir das so gesagt hat. :) )

Gruß
fortuneNext
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von fortuneNext am .
private Nachricht | Beiträge des Benutzers
fortuneNext
myCSharp.de - Member



Dabei seit:
Beiträge: 45
Herkunft: Aachen

Themenstarter:

beantworten | zitieren | melden

Ha, habe doch alles nötige hier.

Also nach dieser Methode zum Laden bekomme ich die Exceptions:
Fehler
{"<ArrayOfXmlAccount xmlns=''> wurde nicht erwartet."}
bzw.
Fehler
Das Objekt des Typs "Aktivenkasse.XmlAccount[]" kann nicht in Typ "System.Collections.Generic.List`1[Aktivenkasse.XmlAccount]" umgewandelt werden.
private Nachricht | Beiträge des Benutzers
inflames2k
myCSharp.de - Experte

Avatar #AARsmmPEUMee0tQa2JoB.png


Dabei seit:
Beiträge: 2.296

beantworten | zitieren | melden

Ich hab mir jetzt mal deine Klasse genommen und die Serialisierung / Deserialisierung getestet.
Bei mir wird die Liste deserialisiert. Ich vermute aber, es liegt an meiner Modifikation deiner Klasse.


public class XmlStructuralAccount : XmlAccount
{
	public List<string> Subaccounts = new List<string>();
}

Allgemein fährst du besser, wenn du Subaccounts zu einer Property machst. Dann funktioniert es auch ohne Initialisierung der Collection:


public class XmlStructuralAccount : XmlAccount
{
	private List<string> _subaccounts;
	public List<string> Subaccounts
	{
		get { return _subaccounts; }
		set { _subaccounts = value; }
	}
}

Meine Methode zum deserialisieren sieht wie folgt aus:


static List<XmlAccount> Deserialize()
{
	List<XmlAccount> accounts = new List<XmlAccount>();

	XmlSerializer serializer = new XmlSerializer(typeof(List<XmlAccount>));
	Stream stream = File.Open("test.xml", FileMode.OpenOrCreate, FileAccess.ReadWrite);
	accounts = (List<XmlAccount>)serializer.Deserialize(stream);
	stream.Close();

	return accounts;
}

Ich hoffe das hilft dir. - Die Methode Deserialize eignet sich so aber nicht für Produktivcode.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von inflames2k am .
Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager | Spielkartenbibliothek
private Nachricht | Beiträge des Benutzers
fortuneNext
myCSharp.de - Member



Dabei seit:
Beiträge: 45
Herkunft: Aachen

Themenstarter:

beantworten | zitieren | melden

Tatsächlich, das hat die Lösung gebracht. Vielen vielen Dank!
private Nachricht | Beiträge des Benutzers