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
Hi 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
Ich könnte hier zwei Aussagen zu machen:
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.
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.
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
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.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
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
Ha, habe doch alles nötige hier.
Also nach dieser Methode zum Laden bekomme ich die Exceptions:
Fehlermeldung:
{"<ArrayOfXmlAccount xmlns=''> wurde nicht erwartet."}
bzw.> Fehlermeldung:
Das Objekt des Typs "Aktivenkasse.XmlAccount[]" kann nicht in Typ "System.Collections.Generic.List`1[Aktivenkasse.XmlAccount]" umgewandelt werden.
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.
Wissen ist nicht alles. Man muss es auch anwenden können.
PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |