Domanda

Il mio repository ha List<Student>, List<Course> e List<Enrolment> dove un iscrizione ha Enrolment.Student e Enrolment.Course che sono riferimenti uno degli studenti o corsi nelle due liste precedenti.

Quando uso XmlSerializer sul mio repository emette dati ridondanti come serializza tutte le proprietà di ogni studente in List<Student> poi di nuovo per ogni riferimento a quegli stessi studenti in List<Enrolment>. Sto cercando un modo elegante per risolvere questo problema.

Dopo la deserializzazione posso risolvere i riferimenti utilizzando i valori ID nelle istanze di oggetti duplicati creati dalla deserializzazione ma questo sembra hacker.

Un metodo per risolvere l'uscita ridondante è quello di XmlIgnore Enrolment.Student e Enrolment.Course e creare più due proprietà per la serializzazione - Enrolment.StudentID e Enrolment.CourseID. Tuttavia durante la deserializzazione, i riferimenti per Enrolment.Student e Enrolment.Course non possono essere impostati (per quanto ne so), in quanto i risultati di deserializzazione di List<Student> e List<Course> non sono disponibili.

Un altro metodo che ho pensato è quello di serializzare più in basso nella mia gerarchia di oggetti facendo ciascuna delle mie liste separatamente e controllare l'ordine di deserializzazione -. Io invece non faccio questo

Un altro metodo sarebbe quello di XmlIgnore List<Enrolment> e creare una classe helper iscrizione serializzazione che inizializza List<Enrolment> dopo la deserializzazione di per sé è completa. Questo mi sembra un grande sforzo.

Come fanno le altre persone serializzare / deserializzare più riferimenti allo stesso oggetto utilizzando XmlSerializer?

È stato utile?

Soluzione

Oh i dolori della serializzazione: -> ...

Non c'è mai stata una soluzione generica per questo, credo che sia il motivo per cui MS spogliato fuori del quadro Silverlight.

Non ho mai contare su alcun meccanismo di serializzazione automatica di .NET framework. Per i miei propri modelli e repository, di solito so o posso facilmente di programmazione determinare quali proprietà sono semplici quelle scalari (numeri / stringhe / etc) e che sono dei link ad altri oggetti (come pure, che sono liste di entrambi).

Ci sono fondamentalmente 2 scenari:

1: Vogliamo serializzare / trasferimento solo le informazioni piatta di oggetti. In tal caso trasferiscono solo i rispettivi ID di oggetti che puntano ad altri oggetti. Il ricevitore può poi fare query successive per ottenere tutti gli altri oggetti di cui hanno bisogno.

2: Vogliamo trasferire quante più informazioni possibile, vale a dire più profondo XML nidificato con diversi livelli, per lo più per un po 'di tutto funzionalità di reporting visualizzazione direttamente utilizzando semplicemente un po' di CSS sul XML. In questo caso, è in realtà desidera che gli oggetti che sono dello stesso saranno risolti più volte nella struttura XML.

A volte ho bisogno di modificare il primo scenario un po 'al fine di evitare troppe chiamate di query successive, ma di solito mi trovo molto bene. Cioè Ho costruito nel nostro codice di base che possiamo specificare quali oggetti supplementari vogliamo risolvere quando, e / o è configurato da qualche parte.

Altri suggerimenti

Non esiste una soluzione per questo problema utilizzando il Serializzatore XML. Non ha un concetto di identità che potrebbe utilizzare per rimuovere la duplicazione.

Il meglio che puoi fare è quello di serializzare il pool di oggetti separatamente dai loro riferimenti. Si potrebbe quindi ricreare le vostre liste dopo la deserializzazione.

A proposito, sono a conoscenza che il XmlSerializer non è specifico per C #?

È possibile implementare l'interfaccia IXmlSerializable di iscrizione e nel metodo WriteXml generare degli studenti e naturalmente XML che sarà contiene solo le chiavi per esempio:.

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

e nel metodo ReadXml è possibile caricare i riferimenti da questo. È inoltre necessario impostare l'attributo XmlIgnore per studenti e Corso di proprietà.

Come funziona questo suono come una soluzione:

  1. XMLIgnore ogni secondaria riferimento cioè Enrolment.Student & Enrolment.Course
  2. creare una proprietà per ogni secondaria riferimento che viene utilizzato per serializzare / deserializzare una chiave esterna per quel riferimento, invece - Prefix con XML_FK. es XML_FK_Student & XML_FK_Course
  3. Creare un metodo che è XML_FinalizeDeserialization chiamato dopo la deserializzazione caricare i riferimenti con quelli esteri proprietà chiave.

Si dovrebbe / possibile utilizzare Monitoraggio di riferimento con il serializzatore 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();

In alternativa, utilizzare

[Serializable]
[DataContract(IsReference = true)]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top