Ho letto ultimamente sulla serializzazione. Ho letto che quando uso XmlSerialization non posso serializzare i grafici degli oggetti. Cos'è un grafo di oggetti e perché non posso serializzarlo semplicemente?Che cos'è un oggetto grafico e come serializzo uno
risposta
Un oggetto grafico non è un singolo oggetto, ma piuttosto un insieme di oggetti correlati. Per un semplice esempio, prendi in considerazione:
public class Node {
public string Name {...}
public Node Parent {...}
public List<Node> Children {...}
}
dove ogni bambino conosce il genitore (e il genitore sa del bambino).
Il problema è che XML è un albero in base alle proprietà degli oggetti ... e vuole loro piedi solo - vale a dire con la semplice padre/figlio:
- A (B sa che è il suo bambino)
- B (sa che A è suo genitore)
che serializzare come:
<Node>
<Name>A</Name>
<!-- no Parent as A is the top node, so null -->
<Children>
<Node>
<Name>B</Name>
<Parent>
<Node>
<Name>A</Name>
*** boom ***
Si può vedere che siamo tornati ad A, quindi siamo ora in un ciclo infinito.
XmlSerializer
può serializzare alberi di dati, ma non grafici completi. È possibile contrassegnare oggetti da essere ignorati, per esempio:
[XmlIgnore]
public Node Parent {...}
E ora che funzionerà, ma dovremo risolvere il Parent
dopo.
Al contrario, alcuni altri serializzatori possono gestire i grafici (DataContractSerializer
può su richiesta). Lo fa rintracciando gli oggetti con una chiave univoca, ma l'output non è quello che ti aspetti da un normale xml.
Un oggetto grafico è un insieme di oggetti che fanno riferimento l'un l'altro.
La serializzazione di un oggetto grafico è complicata. Il serializzatore dovrebbe assegnare un ID univoco a ogni oggetto e quindi sostituire i riferimenti con ID univoci.
Se si stava serializzando in formato XML e si gestivano i grafici degli oggetti, sarebbe necessario aggiungere un attributo "OBJECT_ID" (o qualche altro nome) a ogni elemento. Questo sarebbe molto facile da rompere: cosa succederebbe se aggiungessi una proprietà con lo stesso nome alla classe che stai serializzando?
La soluzione più semplice è quella di non supportarlo.
.NET fornisce la serializzazione binaria che si occupa di questo problema, nonché il problema dei riferimenti circolari.
Un oggetto generale graph consiste in un insieme di riferimenti di detenzione di oggetti. Se si dispone di un albero di oggetti in cui non ci sono collegamenti a ritroso, la serializzazione e la deserializzazione sono semplici. Con un grafico generale, il processo di (de) serializzazione deve tenere traccia dell'identità di ciascun oggetto e utilizzare una qualche forma di algoritmo mark-and-sweep per garantire che gli oggetti non siano (de) serializzati due volte.