2010-01-08 7 views
8

Mein Repository hat List<Student>, List<Course> und List<Enrolment> wo eine Anmeldung Enrolment.Student und Enrolment.Course, die Referenzen eines der Studenten oder Kurse in den beiden vorherigen Listen sind..NET XmlSerializer und mehrere Referenzen auf das gleiche Objekt

Wenn ich XmlSerializer auf meinem Repository verwende, gibt es redundante Daten aus, da es alle Eigenschaften jedes Schülers in List<Student> serialisiert, dann wieder für jede Referenz auf dieselben Studenten in List<Enrolment>. Ich suche nach einem eleganten Weg, um das zu lösen.

Nach der Deserialisierung kann ich die Referenzen mit den ID-Werten in den doppelten Objekt-Instanzen, die durch die Deserialisierung erstellt wurden, beheben, aber das scheint hackish.

Eine Methode, um die redundante Ausgabe zu beheben, besteht darin, XmlIgnore Enrolment.Student und Enrolment.Course zu erstellen und zwei weitere Eigenschaften für die Serialisierung zu erstellen - Enrolment.StudentID und Enrolment.CourseID. Während der Deserialisierung können die Referenzen für Enrolment.Student und Enrolment.Course jedoch nicht festgelegt werden (AFAIK), da die Ergebnisse der Deserialisierung von List<Student> und List<Course> nicht verfügbar sind.

Eine andere Methode, an die ich gedacht habe, ist, tiefer in meiner Objekthierarchie zu serialisieren, indem ich jede meiner Listen einzeln mache und die Reihenfolge der Deserialisierung kontrolliere - das tue ich eher nicht.

Eine andere Methode wäre, XmlIgnore List<Enrolment> und erstellen Sie eine Registrierung Serialisierung Helper-Klasse, die List<Enrolment> initialisiert, nachdem die Deserialisierung von sich abgeschlossen ist. Das scheint eine große Anstrengung zu sein.

Wie serialisieren/deserialisieren andere Personen mehrere Verweise auf dasselbe Objekt mit XmlSerializer?

Antwort

3

Oh die Schmerzen der Serialisierung: -> ...

Es gab nie eine generische Lösung für dieses, ich denke, das ist, warum MS es aus dem Silverlight Rahmen abgestreift.

Ich verlasse mich nie auf irgendwelche automatischen Serialisierungsmechanismen des .net-Frameworks. Für meine eigenen Modelle und Repositories weiß ich normalerweise oder kann leicht programmatisch bestimmen, welche Eigenschaften einfache Skalare sind (Zahlen/Strings/etc) und welche Links zu anderen Objekten sind (und welche Listen von beiden sind).

Es gibt grundsätzlich zwei Szenarien:

1: Wir wollen die Serialisierung/Transfer nur die flachen Informationen von Objekten. In diesem Fall übertrage ich nur die entsprechenden IDs für Eigenschaften, die mit anderen Objekten verknüpft sind. Der Empfänger kann dann nachfolgende Abfragen durchführen, um alle anderen Objekte zu erhalten, die er benötigt.

2: Wir möchten so viele Informationen wie möglich übertragen, d. H. Tiefer verschachteltes XML mit mehreren Ebenen, hauptsächlich für einige Berichtsfunktionen, die alles direkt mit nur einigen CSS auf dem XML anzeigen. In diesem Fall ist es tatsächlich erwünscht, dass Objekte, die identisch sind, mehrfach in den XML-Baum aufgelöst werden.

Manchmal muss ich das erste Szenario ein wenig optimieren, um zu viele nachfolgende Abfrageanrufe zu vermeiden, aber normalerweise komme ich sehr gut zurecht. I.e. Ich habe in unsere Codebasis eingebaut, dass wir angeben können, welche zusätzlichen Objekte wann aufgelöst werden sollen und/oder ob sie irgendwo konfiguriert werden.

+0

Sehr beruhigend - Da ich neu dabei bin, habe ich angenommen, dass ich etwas verpassen muss. Da sich mein Problem auf Ihr erstes Szenario bezieht, werde ich Ihrem Vorschlag folgen, etwas in die Codebasis zu bauen, um die Deserialisierung aufzuräumen. Vielleicht werde ich eine IXmlFinalizeDeserialization erstellen, die über alle meine Objekte hinweg aufgerufen werden kann, um diejenigen zu verfolgen, deren Deserialisierung unzureichend ist, und die Referenzen zu korrigieren. –

2

Es gibt keine Lösung für dieses Problem mit dem XML-Serializer. Es hat kein Identitätskonzept, mit dem es die Duplizierung entfernen könnte.

Das Beste, was Sie tun können, ist, den Pool von Objekten getrennt von ihren Referenzen zu serialisieren. Sie können dann Ihre Listen nach der Deserialisierung neu erstellen.

BTW, wissen Sie, dass der XmlSerializer nicht für C# spezifisch ist?

+0

Dank John - sehr prägnant. Ich habe C# aus meinen Tags entfernt. –

2

Sie können Schnittstelle IXmlSerializable zu Enrollment und in WriteXml Methode generieren Schüler und natürlich XML implementieren, die werden nur Schlüssel enthält z.B .:

<Student Id="5"/> 
<Course Id="6"/> 

und in ReadXml Methode können Sie Referenzen aus diesem laden. Sie müssen außerdem das XmlIgnore-Attribut auf die Eigenschaft Student und Course festlegen.

+0

Das Problem bei diesem Ansatz besteht darin, dass Sie während ReadXml keine Referenzen (AFAIK) zu anderen Daten laden können, die ebenfalls deserialisiert werden, da sie erst verfügbar sind, wenn die Deserialisierung abgeschlossen ist. Kennst du das irgendwie? –

0

Wie klingt das als Lösung:

  1. XmlIgnore jeder sekundäre Referenz dh Enrolment.Student & Enrolment.Course
  2. eine Eigenschaft für jede Sekundär Referenz erstellen, die auf serialize verwendet wird/Deserialize einen fremden Schlüssel für diese Referenz stattdessen - Präfix mit XML_FK. zB XML_FK_Student & XML_FK_Course
  3. ein Verfahren XML_FinalizeDeserialization erstellen, die nach der Deserialisierung aufgerufen wird die Verweise zu laden, diese fremden Schlüsseleigenschaften verwenden.
+1

Wäre es nicht schön, wenn wir ein Attribut [XmlSecondary] erstellen könnten, das einem Verweis vorangestellt wird, der den XML_Serializer veranlasst, den Verweis auf Felder mit dem Präfix [XMLPK] zu prüfen und nur diese auszugeben? Möglich? –

+0

Ziemlich möglich, aber Sie müssten dann Ihren eigenen Serializer schreiben, um das Attribut zu erkennen, und ich denke, Sie wollen das nicht tun. –

Verwandte Themen