Question

Mon dépôt a List<Student>, List<Course> et List<Enrolment> où une inscription a Enrolment.Student et Enrolment.Course qui sont des références un des étudiants ou des cours dans les deux listes précédentes.

Quand j'utilise XmlSerializer sur mon dépôt, il transmet les données redondantes car il sérialise toutes les propriétés de chaque élève en List<Student> puis de nouveau pour chaque référence à ces mêmes étudiants dans List<Enrolment>. Je cherche une façon élégante de résoudre ce problème.

Après désérialisation je peux fixer les références en utilisant les valeurs d'identité dans les instances d'objets en double créés par le désérialisation, mais cela semble hackish.

Une méthode pour fixer la sortie redondante est de XmlIgnore Enrolment.Student et Enrolment.Course et créer deux propriétés pour sérialisation - Enrolment.StudentID et Enrolment.CourseID. Cependant lors de la désérialisation, les références pour Enrolment.Student et Enrolment.Course ne peuvent pas être réglés (AFAIK) étant donné que les résultats de désérialisation de List<Student> et List<Course> ne sont pas disponibles.

Une autre méthode que je pensais est de sérialisation plus bas dans ma hiérarchie d'objets faisant chacun de mes listes séparément et contrôler l'ordre de désérialisation -. Je préfère ne pas faire ça

Une autre méthode serait de XmlIgnore List<Enrolment> et créer une classe d'aide de sérialisation d'inscription initialisant List<Enrolment> après la désérialisation elle-même est terminée. Cela semble beaucoup d'efforts.

Comment les autres linéariser / désérialiser multiples références au même objet en utilisant XmlSerializer?

Était-ce utile?

La solution

Oh les douleurs de sérialisation: -> ...

Il n'y a jamais une solution générique pour cela, je pense que c'est pourquoi MS il dépouillé du cadre Silverlight.

Je ne compte sur aucun mécanisme de sérialisation automatique du cadre de .net. Pour mes propres modèles et référentiels, je sais habituellement ou peut facilement déterminer par un programme dont les propriétés sont simples scalaires (nombres / chaînes / etc) et qui sont des liens vers d'autres objets (ainsi que qui sont des listes de non plus).

Il y a essentiellement 2 scénarios:

1: Nous voulons sérialisation / transfert uniquement les informations d'objets plats. Dans ce cas, je ne transférer que les ID respectifs pour les propriétés qui pointent vers d'autres objets. Le récepteur peut alors effectuer des requêtes suivantes pour obtenir tous les autres objets dont ils ont besoin.

2: Nous voulons transférer autant d'informations que possible, à savoir XML plus profond imbriquée avec plusieurs niveaux, la plupart du temps pour certains tout afficher des fonctionnalités de reporting directement en utilisant simplement un peu de CSS sur le XML. Dans ce cas, il est effectivement souhaité que les objets qui sont les mêmes seront résolus à plusieurs reprises dans l'arborescence XML.

Parfois, je besoin de modifier le premier scénario un peu afin d'éviter un trop grand nombre d'appels de requête suivants, mais le plus souvent je reçois très bien. C'est à dire. Je l'ai construit dans notre base de code que nous pouvons spécifier les objets supplémentaires que nous voulons résoudre quand, et / ou il est configuré quelque part.

Autres conseils

Il n'y a pas de solution à ce problème en utilisant le sérialiseur XML. Il ne dispose pas d'un concept d'identité qu'il pourrait utiliser pour supprimer les doublons.

Le mieux que vous pouvez faire est de sérialiser la piscine d'objets séparément de leurs références. Vous pouvez ensuite recréer vos listes après désérialisation.

BTW, savez-vous que le XmlSerializer est pas spécifique à C #?

Vous pouvez implémenter IXmlSerializable d'interface pour inscription et dans la méthode WriteXml générer XML étudiants et des cours qui ne contient que des clés sera par exemple:.

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

et dans la méthode ReadXml vous pouvez charger des références de cette situation. Vous devez également définir l'attribut XmlIgnore à la propriété et aux étudiants du cours.

Comment ce son comme une solution:

  1. XMLIgnore chaque secondaire référence à savoir Enrolment.Student & Enrolment.Course
  2. créer une propriété pour chaque secondaire référence qui est utilisé pour linéariser / désérialiser une clé étrangère pour cette référence au lieu - Prefix avec XML_FK. par exemple XML_FK_Student & XML_FK_Course
  3. Créer une XML_FinalizeDeserialization méthode qui est appelé après la désérialisation pour charger les références utilisant les étrangers propriétés clés.

Vous devez / pouvez utiliser le suivi de référence avec le sérialiseur DataContract:

//deserilaize:
using(MemoryStream memStmBack = new MemoryStream()) {
  var serializerForth = new DataContractSerializer(
    typeof(YourType),
    null,
    0x7FFF /*maxItemsInObjectGraph*/ ,
    false /*ignoreExtensionDataObject*/ ,
    true /*preserveObjectReferences*/ ,
    null /*dataContractSurrogate*/ );

  byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
  memStmBack.Write(data, 0, data.Length);
  memStmBack.Position = 0;
  var lsBack = (YourType) serializerForth.ReadObject(memStmBack);

}
//serialize...
using(MemoryStream memStm = new MemoryStream()) {
    var serializer = new DataContractSerializer(
      typeof(YourType),
      knownTypes,
      0x7FFF /*maxItemsInObjectGraph*/ ,
      false /*ignoreExtensionDataObject*/ ,
      true /*preserveObjectReferences*/ ,
      null /*dataContractSurrogate*/ );

    serializer.WriteObject(memStm, yourType);

    memStm.Seek(0, SeekOrigin.Begin);

    using(var streamReader = new StreamReader(memStm)) {
        result = streamReader.ReadToEnd();

Ou utilisez

[Serializable]
[DataContract(IsReference = true)]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top