Utilizzando .Net quali limitazioni (se presenti) ci sono nell'uso di XmlSerializer?

StackOverflow https://stackoverflow.com/questions/109318

  •  01-07-2019
  •  | 
  •  

Domanda

Uso di .Net quali sono le limitazioni (se presenti) nell'uso di XmlSerializer? Ad esempio, puoi serializzare le immagini in XML?

È stato utile?

Soluzione

XmlSerializer presenta alcuni inconvenienti.

  1. Deve conoscere tutti i tipi in fase di serializzazione. Non è possibile passare qualcosa dall'interfaccia che rappresenta un tipo che il serializzatore non conosce.
  2. Non può fare riferimenti circolari.
  3. Serializzerà lo stesso oggetto più volte se indicato più volte nel grafico degli oggetti.
  4. Impossibile gestire la serializzazione del campo privato.

Ho (stupidamente) scritto il mio serializzatore per aggirare alcuni di questi problemi. Non farlo; è un sacco di lavoro e troverai bug sottili in questi mesi lungo la strada. L'unica cosa che ho guadagnato scrivendo il mio serializzatore e il mio formattatore era un maggiore apprezzamento della minutia implicata nella serializzazione dei grafi di oggetti.

Ho trovato NetDataContractSerializer quando WCF venne fuori. Fa tutto ciò che dall'alto non fa XmlSerializer. Gestisce la serializzazione in modo simile a XmlSerializer. Uno decora varie proprietà o campi con attributi per informare il serializzatore su cosa serializzare. Ho sostituito il serializzatore personalizzato che avevo scritto con NetDataContractSerializer ed ero molto soddisfatto dei risultati. Lo consiglio vivamente.

Altri suggerimenti

In genere trovo XmlSerializer una scelta sbagliata per qualsiasi POCO che è più di un semplice DTO. Se hai bisogno di XML specifico, puoi andare sull'attributo Xml * e / o IXmlSerializable route - ma ti rimane un oggetto piuttosto maledetto.

Per alcuni scopi, è ancora una scelta ovvia, anche con i suoi limiti. Ma, per archiviare e ricaricare semplicemente i dati, ho trovato BinaryFormatter una scelta molto più semplice con meno insidie.

Ecco un elenco di alcuni fastidi con XmlSerializer - la maggior parte dei quali sono stato morso da un punto o dall'altro, altri che ho trovato su MSDN :

  • Richiede un costruttore pubblico, senza args
  • Serializza solo proprietà e campi pubblici in lettura / scrittura
  • Richiede che tutti i tipi siano conosciuti
  • In realtà chiama in get_ * e set_ *, quindi verrà eseguita la convalida, ecc. Questo può essere positivo o negativo (pensa anche all'ordine delle chiamate)
  • Serializzerà solo raccolte IEnumerable o ICollection conformi a regole specifiche
  

XmlSerializer offre un trattamento speciale alle classi che implementano IEnumerable o ICollection. Una classe che implementa IEnumerable deve implementare un metodo Add pubblico che accetta un singolo parametro. Il parametro del metodo Add deve essere dello stesso tipo restituito dalla proprietà Current sul valore restituito da GetEnumerator o da una delle basi di quel tipo.

     

Una classe che implementa ICollection (come CollectionBase) oltre a IEnumerable deve avere una proprietà indicizzata Item pubblica (indicizzatore in C #) che accetta un numero intero e deve avere una proprietà Count pubblica di tipo intero. Il parametro per il metodo Add deve essere dello stesso tipo restituito dalla proprietà Item o da una delle basi di quel tipo. Per le classi che implementano ICollection, i valori da serializzare vengono recuperati dalla proprietà Item indicizzata, non chiamando GetEnumerator.

  • Non serializza IDictionary
  • Utilizza assembly generati dinamicamente, che potrebbero non essere scaricati dal dominio dell'app.
  

Per aumentare le prestazioni, l'infrastruttura di serializzazione XML genera dinamicamente assembly per serializzare e deserializzare tipi specifici. L'infrastruttura trova e riutilizza tali assiemi. Questo comportamento si verifica solo quando si utilizzano i seguenti costruttori:

     

XmlSerializer.XmlSerializer (Type)   XmlSerializer.XmlSerializer (Type, String)

     

Se si utilizza uno degli altri costruttori, vengono generate e non scaricate più versioni dello stesso assieme, con conseguente perdita di memoria e prestazioni scadenti.

  • Impossibile serializzare ArrayList [] o List < T > []
  • Ha altri casi con bordi strani
  

XmlSerializer non può essere istanziato per serializzare un'enumerazione se sono vere le seguenti condizioni: L'enumerazione è di tipo unsigned long (ulong in C #) e l'enumerazione contiene qualsiasi membro con un valore maggiore di 9.223.372.036.854.775.807.

     

La classe XmlSerializer non serializza più oggetti contrassegnati come [Obsoleto].

     

È necessario disporre dell'autorizzazione per scrivere nella directory temporanea (come definita dalla variabile d'ambiente TEMP) per deserializzare un oggetto.

  • Richiede la lettura .InnerException per ottenere informazioni utili sugli errori

Un altro problema è che chiamando il costruttore di XmlSerializer compilerà il codice in fase di esecuzione e genererà una DLL temporanea (nella cartella% temp%) con il codice per eseguire la de / serializzazione.

Puoi guardare il codice se aggiungi le seguenti righe a app.config:

  <system.diagnostics>
    <switches>
      <add name="XmlSerialization.Compilation" value="4"/>
    </switches>
  </system.diagnostics>

Questo richiede molto tempo la prima volta che serializzi una classe e hai bisogno di codice con autorizzazioni per compilare e scrivere su disco.

Un modo per aggirare il problema è precompilare queste DLL usando lo strumento sGen.exe fornito con VS 2005+.

Cerca qui ulteriori informazioni .

Non sono sicuro che ci sia qualche limitazione .. Ma c'era un bug di perdita di memoria in XmlSerialization in .NET 1.1, hai dovuto creare un oggetto serializzatore di cache per ovviare a questo problema ... In effetti, non sono sicuro se questo problema è stato risolto in .net 2.0 o versioni successive ...

Qualunque classe che scrivi può teoricamente essere alimentata tramite XmlSerializer. Inoltre, ha accesso solo ai campi pubblici e le classi devono essere contrassegnate con gli attributi corretti (ad esempio XmlAttribute). Anche nel framework di base, non tutto supporta XmlSerializer. System.Collections.Generic.Dictionary lt &; & Gt; per esempio.

L'unica limitazione che mi viene in mente è che XmlSerialization è opt-out; vale a dire qualsiasi proprietà di una classe che non si desidera serializzare DEVE essere decorata con [XmlIgnore]. In contrasto con DataContractSerializer in cui tutte le proprietà sono attive, è necessario dichiarare esplicitamente gli attributi di inclusione. Ecco un buon scrivere-up .

Le immagini o i loro array binari sono serializzati come testo codificato in base64 da XmlSerializer.

Ad esempio, non è possibile serializzare le classi che implementano l'interfaccia IDictionary.

Per le raccolte devono avere un metodo Add che accetta un singolo argomento. Se hai solo bisogno di un formato di testo e non specificamente di XML puoi provare JSON. Ne ho sviluppato uno per .NET, JsonExSerializer , e ce ne sono altri disponibili anche su http://www.json.org .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top