Quelle est la sérialisation la plus flexible pour les objets .NET, mais simple à implémenter?

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

Question

Je souhaite sérialiser et désérialiser des objets sans avoir à se soucier du graphe de classe entier.

La flexibilité est la clé. J'aimerais pouvoir sérialiser n'importe quel objet qui m'a été transmis sans les attributs complets nécessaires dans tout le graphe d'objets.

  

Cela signifie que la sérialisation binaire   n'est pas une option car il ne fonctionne qu'avec   les autres plates-formes .NET. je voudrais   aussi comme quelque chose de lisible par un   personne, et donc déchiffrable par un   programme de gestion et autres   interprètes.

J'ai rencontré des problèmes d'utilisation des sérialiseurs DataContract, JSON et XML.

  • La plupart de ces erreurs semblent être liées à la sérialisation des listes / dictionnaires ( Dictionnaire générique XML sérialisable ).
  • " Ajouter des types inconnus statiquement à la liste des types connus - pour exemple, en utilisant le KnownTypeAttribute ou par en les ajoutant à la liste des connus types passés à DataContractSerializer. & Quot;

Veuillez baser vos réponses sur des expériences réelles et non sur la théorie ou la lecture d'un article.

Était-ce utile?

La solution

Avez-vous envisagé de sérialiser en JSON au lieu de XML?

Json.NET possède un sérialiseur très puissant et flexible qui ne pose aucun problème avec Hashtables / dictionnaires génériques et ne nécessite aucun attribut particulier. Je sais parce que je l'ai écrit:)

Il vous donne un tas de contrôle à travers différentes options du sérialiseur et vous permet de modifier la façon dont un type est sérialisé en créant un convertisseur Json pour ce dernier.

À mon avis, JSON est plus lisible que XML et Json.NET donne la possibilité d'écrire du JSON correctement formaté.

Enfin, le projet est open source afin que vous puissiez entrer dans le code et y apporter des modifications si nécessaire.

Autres conseils

Si je me souviens bien, cela fonctionne comme ceci avec une propriété:

[XmlArray("Foo")]
[XmlArrayItem("Bar")]
public List<BarClass> FooBars
{ get; set; }

Si vous avez sérialisé cela, vous obtiendrez quelque chose comme:

<Foo>
    <Bar />
    <Bar />
</Foo>

Bien sûr, je devrais probablement m'en remettre aux experts. Voici plus d'informations sur MS: http: // msdn. microsoft.com/en-us/library/system.xml.serialization.xmlarrayitemattribute.aspx

Faites-moi savoir si cela vous convient.

D'après vos exigences, il semble que la sérialisation XML soit préférable.

Quel genre de problèmes avez-vous avec les collections lors de la sérialisation? Si vous parlez de ne pas savoir quels attributs utiliser sur une liste ou quelque chose de similaire, vous pouvez essayer le Attribut XmlArray sur votre propriété. Vous pouvez certainement sérialiser une collection.

L'IntermediateSerializer dans XNA Framework est vraiment cool. Vous pouvez trouver de nombreux didacticiels sur son utilisation à l'adresse http://blogs.msdn.com/shawnhar .

La sérialisation SOAP a bien fonctionné pour moi, même pour les objets non marqués avec [Serializable]

La sérialisation de la collection posera des problèmes si les objets de la collection contiennent une référence à d'autres objets de la même collection. S'il existe un type de double pointage, vous créez une multi-carte qui ne peut pas être sérialisée. Pour chaque problème que j'ai rencontré lors de la sérialisation d'une collection personnalisée, c'était toujours à cause de certaines fonctionnalités supplémentaires dont j'avais besoin et qui fonctionnaient parfaitement dans le cadre d'un processus "typique". application client-serveur, puis a échoué lamentablement dans le cadre d’une application client-fournisseur-serveur.

Placez toutes les classes que vous souhaitez sérialiser dans un assemblage séparé, puis utilisez l'outil sgen pour générer un assemblage de sérialisation à sérialiser en XML. Utilisez des attributs XML pour contrôler la sérialisation.

Si vous devez personnaliser l'assemblage de sérialisation (et vous en aurez besoin pour prendre en charge des classes autres que IXmlSerializable et des classes contenant des nœuds abstraits), demandez à sgen de vider le code source dans un fichier. fichier séparé, puis ajoutez-le à votre solution. Ensuite, vous pouvez le modifier si nécessaire.

http://msdn.microsoft.com/ en-us / library / bk3w6240 (VS.80) .aspx

FWIW, j’ai réussi à sérialiser l’ensemble du cadre AdsML (plus de 400 classes) à l’aide de cette technique. Cela nécessitait beaucoup de personnalisation manuelle, mais il n’ya pas de solution de rechange si l’on prend en compte la taille du cadre. (J'ai utilisé un outil séparé pour passer de XSD à C #)

Je conviens que les méthodes de sérialisation basées sur DataContract (JSON, XML, etc.) sont un peu plus complexes que je ne le souhaiterais.

Si vous essayez d’obtenir JSON, consultez http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx

Cela fait partie des extensions MS AJAX. Certes, il est signalé comme obsolète dans .NET 3.5, mais ScottGu mentionne dans son commentaire de blog ici ( http://weblogs.asp.net/scottgu/archive/2007/10/01/tip-trick -building-a-tojson-extension-method-using-net-3-5.aspx # 4301973 ) qu'il ne sait pas pourquoi et qu'il devrait être pris en charge un peu plus longtemps.

La solution la plus simple consiste à marquer vos objets avec l'attribut Serializable, puis à utiliser un formateur binaire pour gérer la sérialisation. L’intégralité du graphe de classe ne devrait pas poser de problème à condition que tous les objets contenus soient également marqués comme étant Serializable.

Une méthode plus efficace consisterait peut-être à effectuer une sérialisation à l'aide de BinaryFormatter

Copié à partir de http://blog.paranoidferret.com/index.php/2007/04/27/csharp-tutorial-serialize-objects-to-a-file/

using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class Serializer
{
   public Serializer()
   {
   }

   public void SerializeObject(string filename,
                  ObjectToSerialize objectToSerialize)
   {
      Stream stream = File.Open(filename, FileMode.Create);
      BinaryFormatter bFormatter = new BinaryFormatter();
      bFormatter.Serialize(stream, objectToSerialize);
      stream.Close();
   }

   public ObjectToSerialize DeSerializeObject(string filename)
   {
      ObjectToSerialize objectToSerialize;
      Stream stream = File.Open(filename, FileMode.Open);
      BinaryFormatter bFormatter = new BinaryFormatter();
      objectToSerialize =
         (ObjectToSerialize)bFormatter.Deserialize(stream);
      stream.Close();
      return objectToSerialize;
   }
}

Pour l’interopérabilité, nous avons toujours utilisé la sérialisation XML et nous nous sommes assurés que notre classe a été conçue pour le faire correctement.

Nous créons un document de schéma XSD et générons un ensemble de classes à partir de celui-ci en utilisant XSD.exe. Ceci génère des classes partielles. Nous créons ensuite un ensemble de classes partielles correspondantes pour ajouter les méthodes supplémentaires que nous voulons nous aider à peupler les classes et à les utiliser dans notre application (car elles sont concentrées sur la sérialisation et la désérialisation et sont un peu difficiles à utiliser parfois. ).

Vous devez utiliser NetDataContractSerializer. Il couvre tout type de graphe d'objet et prend en charge les génériques, les listes, le polymorphisme (l'attribut KnownType n'est pas nécessaire ici), la récursivité, etc. Le seul inconvénient est que vous devez marquer toutes vos classes avec les attributs [Serializable] / [DataContract], mais l'expérience montre que vous devez de toute façon procéder à un réglage manuel, car tous les membres ne doivent pas être persistants. En outre, il se sérialise dans un fichier XML, bien que sa lisibilité soit discutable.

Nous avions les mêmes exigences que la vôtre et avons choisi cette solution.

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