Utilisation de .Net Quelles sont les limites (le cas échéant) à l’utilisation de XmlSerializer?

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

  •  01-07-2019
  •  | 
  •  

Question

Utilisation de .Net, quelles sont les limitations (le cas échéant) concernant l’utilisation de XmlSerializer? Par exemple, pouvez-vous sérialiser les images en XML?

Était-ce utile?

La solution

XmlSerializer présente quelques inconvénients.

  1. Il doit connaître tous les types en cours de sérialisation. Vous ne pouvez pas transmettre quelque chose par interface qui représente un type inconnu du sérialiseur.
  2. Il ne peut pas faire de références circulaires.
  3. Il sérialisera le même objet plusieurs fois s'il est référencé plusieurs fois dans le graphe d'objets.
  4. Impossible de gérer la sérialisation des champs privés.

J'ai écrit (bêtement) mon propre sérialiseur pour résoudre certains de ces problèmes. Ne fais pas ça c'est beaucoup de travail et vous trouverez des bugs subtils dans les mois à venir. La seule chose que j'ai gagnée en écrivant mon propre sérialiseur et formateur a été une meilleure compréhension de la minutie impliquée dans la sérialisation de graphe d'objet.

J'ai trouvé le NetDataContractSerializer lorsque WCF sortit de. Il fait tout ce qui précède que XmlSerializer ne fait pas. Il pilote la sérialisation de la même manière que XmlSerializer. L'un décore diverses propriétés ou champs avec des attributs pour informer le sérialiseur de ce qu'il doit sérialiser. J'ai remplacé le sérialiseur personnalisé que j'avais écrit avec le NetDataContractSerializer et j'étais très heureux des résultats. Je le recommande vivement.

Autres conseils

Je trouve généralement que XmlSerializer est un mauvais choix pour tout POCO qui dépasse le simple DTO. Si vous avez besoin de XML spécifique, vous pouvez utiliser l'attribut Xml * Attribute et / ou IXmlSerializable, mais il vous reste un objet assez déformé.

À certaines fins, il reste un choix évident, même avec ses limitations. Mais, pour simplement stocker et recharger des données, j'ai trouvé que BinaryFormatter était un choix beaucoup plus facile avec moins de pièges.

Voici une liste de certains désagréments liés à XmlSerializer - la plupart des personnes qui m'ont mordu à un moment ou à un autre, d'autres que j'ai trouvées à MSDN :

  • Nécessite un constructeur public, no args
  • sérialise uniquement les propriétés et les champs en lecture / écriture publics
  • Requiert la connaissance de tous les types
  • Appelle réellement dans get_ * et set_ *, ainsi la validation, etc. sera exécutée. Cela peut être bon ou mauvais (pensez aussi à l'ordre des appels)
  • ne sérialisera que les collections IEnumerable ou ICollection conformes à des règles spécifiques
  

XmlSerializer accorde un traitement spécial aux classes qui implémentent IEnumerable ou ICollection. Une classe qui implémente IEnumerable doit implémenter une méthode publique Add qui prend un seul paramètre. Le paramètre de la méthode Add doit être du même type que celui renvoyé par la propriété Current sur la valeur renvoyée par GetEnumerator ou par l'une des bases de ce type.

     

Une classe qui implémente ICollection (telle que CollectionBase) en plus de IEnumerable doit avoir une propriété publique Item indexée (indexeur en C #) prenant un entier, et une propriété publique Count de type entier. Le paramètre de la méthode Add doit être du même type que celui renvoyé par la propriété Item ou de l'une des bases de ce type. Pour les classes qui implémentent ICollection, les valeurs à sérialiser sont extraites de la propriété Item indexée et non en appelant GetEnumerator.

  • Ne sérialise pas IDictionary
  • Utilise des assemblys générés de manière dynamique, qui peuvent ne pas être déchargés du domaine d'application.
  

Pour améliorer les performances, l'infrastructure de sérialisation XML génère de façon dynamique des assemblys pour sérialiser et désérialiser les types spécifiés. L'infrastructure trouve et réutilise ces assemblages. Ce problème se produit uniquement lors de l'utilisation des constructeurs suivants:

     

XmlSerializer.XmlSerializer (Type)   XmlSerializer.XmlSerializer (Type, Chaîne)

     

Si vous utilisez l'un des autres constructeurs, plusieurs versions du même assemblage sont générées et ne sont jamais déchargées, ce qui entraîne une fuite de mémoire et des performances médiocres.

  • Impossible de sérialiser ArrayList [] ou List < T > []
  • a d'autres cas étranges
  

XmlSerializer ne peut pas être instancié pour sérialiser une énumération si les conditions suivantes sont remplies: L'énumération est de type unsigned long (ulong en C #) et contient l'un des membres dont la valeur est supérieure à 9 223 372 036 854 775 807.

     

La classe XmlSerializer ne sérialise plus les objets marqués comme [Obsolète].

     

Vous devez avoir le droit d'écrire dans le répertoire temporaire (tel que défini par la variable d'environnement TEMP) pour désérialiser un objet.

  • Requiert la lecture de .InnerException pour obtenir des informations utiles sur les erreurs

Un autre problème est que l'appel du constructeur de XmlSerializer compilera le code lors de l'exécution et générera une DLL temporaire (dans le dossier% temp%) avec le code permettant d'effectuer la dés / sérialisation.

Vous pouvez regarder le code si vous ajoutez les lignes suivantes à app.config:

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

Cela prend beaucoup de temps la première fois que vous sérialisez une classe et a besoin de code avec des autorisations pour la compilation et l'écriture sur le disque.

Un moyen de contourner ce problème consiste à précompiler ces DLL à l'aide de l'outil sGen.exe fourni avec VS 2005+.

Cliquez ici pour plus d'informations .

Je ne sais pas s'il y a une quelconque limitation .. Mais il y avait un bogue de fuite de mémoire dans XmlSerialization dans .NET 1.1, vous deviez en quelque sorte créer un objet de sérialiseur de cache pour résoudre ce problème ... En fait, je ne suis pas sûr si ce problème a été corrigé dans .net 2.0 ou plus récent ...

Toute classe que vous écrivez peut théoriquement être alimentée via XmlSerializer. Cependant, il n'a accès qu'aux champs publics et les classes doivent être marquées avec les attributs appropriés (par exemple, XmlAttribute). Même dans le cadre de base, tout ne prend pas en charge XmlSerializer. System.Collections.Generic.Dictionary & Lt; & Gt; par exemple.

La seule limitation à laquelle je peux penser est que XmlSerialization est opt-out; signifiant que toutes les propriétés d'une classe que vous ne voulez pas sérialiser DOIVENT être décorées avec [XmlIgnore]. Contrairement à DataContractSerializer où toutes les propriétés sont acceptées, vous devez déclarer explicitement les attributs d'inclusion. Voici un bon rédiger .

Les images ou leurs tableaux binaires sont sérialisées sous forme de texte codé en base64 par XmlSerializer.

Par exemple, vous ne pouvez pas sérialiser les classes implémentant l'interface IDictionary.

Pour les collections, ils doivent avoir une méthode Add prenant un seul argument. Si vous avez juste besoin d'un format texte et pas spécifiquement xml, essayez JSON. J'en ai développé un pour .NET, JsonExSerializer , et d'autres sont également disponibles à http://www.json.org .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top