Autor Beitrag
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Fr 24.08.12 19:15 
Moin

Ich habe hier eine kleine Umfrage für die Schule liegen, die ich spaßeshalber von einem fix entworfenem Programm so weit wie möglich auswerten lassen will.
Dazu habe ich eine Basisklasse für jede Frage und zwei Fragen, die davon erben; einmal die "normalen" Fragen und dann die Entscheidungs-Fragen.
Zusätzlich habe ich noch eine Klasse, die das ganze auf listet und verwaltet. Das auswerten wird von einer statischen Methode übernommen und ist auch so im Moment nicht wichtig.
Woran es bei mir scheitert ist das Speichern, wofür ich XML ausgewählt habe, weil es am einfachsten zu handhaben ist, wenn man nur einen Text-Editor hat.
In der Klasse, die zum Auflisten und Verwalten gedacht ist, speichere ich die Daten in einem Dictionary. Der Key ist vom Typ int und Value ist vom Typ der Basis-Fragen-Klasse.
Da ein Dictionary von Haus aus nicht serialisiert werden kann, habe ich IXMLSerialisable implementiert und zwar so:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
        public XmlSchema GetSchema()
        {
            return null;
        }
        public void ReadXml(XmlReader reader)
        {
            XmlSerializer keySerializer = new XmlSerializer(typeof(int));
            XmlSerializer valueSerializer = new XmlSerializer(typeof(Question));
            bool wasEmpty = reader.IsEmptyElement;
            reader.Read();
            if (wasEmpty) return;
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                reader.ReadStartElement("questionItem");
                reader.ReadStartElement("number");
                int key = (int)keySerializer.Deserialize(reader);
                reader.ReadEndElement();
                reader.ReadStartElement("question");
                Question value = (Question)valueSerializer.Deserialize(reader);
                reader.ReadEndElement();
                this.Questions.Add(key, value);
                reader.ReadEndElement();
                reader.MoveToContent();
            }
            reader.ReadEndElement();
        }
        public void WriteXml(XmlWriter writer)
        {
            XmlSerializer keySerializer = new XmlSerializer(typeof(int));
            XmlSerializer valueSerializer = new XmlSerializer(typeof(Question));
            foreach (int key in this.Questions.Keys)
            {
                writer.WriteStartElement("questionItem");
                writer.WriteStartElement("number");
                keySerializer.Serialize(writer, key);
                writer.WriteEndElement();
                writer.WriteStartElement("question");
                var value = this.Questions[key];
                valueSerializer.Serialize(writer, value);
                writer.WriteEndElement();
                writer.WriteEndElement();
            }
        }


Wenn ich dann nun eine Entscheidungs-Frage in die Auflistung mit einer Reihe Antworten einlese und speichern lassen will, wird der Fehler ausgegeben, dass dieser Typ nicht erwartet wurde und ich XmlInclude verwenden soll.

Ich habe von dem Fehler bisher nur gelesen und weiß auch wozu das gut ist, aber scheinbar habe ich nicht kapiert, wo genau es nun hin muss. Ich habe nahezu jede Methode ausprobiert und auch die Klasse selber habe ich damit ausgerüstet, nur zum testen, es gab immer wieder den Fehler.


Kann mir vielleicht jemand erklären, wo genau das hin muss?
Abgeleitete Klassen verwende ich zu Genüge und speichere sie ständig unter dem Typ der Basis-Klasse, da müsste es doch eigentlich reichen, die Klasse komplett mit dem Attribut zu versehen, oder?


Gruß
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 24.08.12 20:00 
Hallo Palladin700,

du scheinst ja eine eigene Abwandlung von XML Serializable Generic Dictionary zu benutzen.

Wie aber sehen denn deine Fragen-Klassen (Question, "Normale Frage", "Entscheidungs-Frage") aus? Hast du dort evtl. Readonly-Properties, welche nicht serialisiert werden können?

Schau dir auch mal die Seite Troubleshooting Common Problems with the XmlSerializer an...
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4708
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 24.08.12 20:27 
Zitat:
Kann mir vielleicht jemand erklären, wo genau das hin muss?


Der Serializer muß alle Ableitungen kennen. Damit er die Serializer Assemblies auch für alle Ableitungen erzeugen kann aber er eigentlich nur die Basisklasse übergeben bekommt ist klar das das XMLInclude Attribut an die Basisklasse gehört.

z.B.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
[XmlInclude(typeof(NameDerAbleitungVonQuestion1))]
[XmlInclude(typeof(NameDerAbleitungVonQuestion2))]
public class Question
{
 .. blah
}


Und, bevor du rummeckers ;), ja das ist doof.

Edit : Das gilt natürlich auch für alle von Question veröffentlichten Properties die Typen veröffentlichen mit Ableitungen die potentiell auch serialisiert werden wollen. Die mußt du auch alle per XmlInclude bekanntmachen.
Palladin007 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Fr 24.08.12 21:28 
@Th69:

Da ist alles auf public gesetzt, das einzige, was vielleicht ein Problem sein könnte, ist ein Enum, das in der Klasse für die Entscheidungs-Frage gesetzt werden soll. Aber das ist kein Problem, oder?


@Ralf Jansen:
Ich probiere das gleich mal aus. So habe ich nämlich noch nicht gedacht ^^



Edit:
Ja, jetzt funktioniert es :D
Danke, jetzt hab ich dieses Attribut auch endlich mal verstanden ^^


Gruß