XmlSerializer.Deserialize() n'est pas la désérialisation d'une Liste<T> correctement
Je suis nouveau sur le C# XmlSerializer donc j'ai peut-être raté quelque chose de base ici.
Le problème, je suis en cours d'exécution, c'est que j'ai une classe qui a un List<T>
d'une autre classe. Quand je sérialiser la classe principale de l'XML est magnifique et toutes les données sont intactes. Quand je désérialiser le XML, les données dans le List<T>
disparait et je suis parti avec un vide List<T>
. Je ne reçois pas toutes les erreurs et la sérialisation partie fonctionne comme un charme.
Ce qui me manque avec le processus de désérialisation?
EDIT: Noter que le code ci-dessous ne permet pas de reproduire le problème, il fonctionne. C'était une version simplifiée du code réel, qui n'a pas travail. Malheureusement, le code ci-dessous a été simplifié assez pour ne pas reproduire le problème!
public class User
{
public User()
{
this.Characters = new List<Character>();
}
public string Username { get; set; }
public List<Character> Characters { get; set; }
}
public class Character
{
public Character()
{
this.Skills = new List<Skill>();
}
public string Name { get; set; }
public List<Skill> Skills { get; set; }
}
public enum Skill
{
TreeClimber,
ForkliftOperator
}
public static void Save(User user)
{
using (var textWriter = new StreamWriter("data.xml"))
{
var xmlSerializer = new XmlSerializer(typeof(User));
xmlSerializer.Serialize(textWriter, user);
}
}
public static User Restore()
{
if (!File.Exists("data.xml"))
throw new FileNotFoundException("data.xml");
using (var textReader = new StreamReader("data.xml"))
{
var xmlSerializer = new XmlSerializer(typeof(User));
return (User)xmlSerializer.Deserialize(textReader);
}
}
public void CreateAndSave()
{
var character = new Character();
character.Name = "Tranzor Z";
character.Skills.Add(Skill.TreeClimber);
var user = new User();
user.Username = "Somebody";
user.Characters.Add(character);
Save(user);
}
public void RestoreAndPrint()
{
var user = Restore();
Console.WriteLine("Username: {0}", user.Username);
Console.WriteLine("Characters: {0}", user.Characters.Count);
}
Le XML généré par l'exécution de CreateAndSave() ressemble à ceci:
<User>
<Username>Somebody</Username>
<Characters>
<Character>
<Name>Tranzor Z</Name>
<Skills>
<Skill>TreeClimber</Skill>
</Skills>
</Character>
<Characters>
</User>
Parfait! C'est la façon dont il devrait ressembler. Si je puis exécuter RestoreAndPrint()
- je obtenir un objet Utilisateur avec le nom d'utilisateur de propriété définis correctement, mais les Caractères de la propriété est une liste vide:
Username: Somebody
Characters: 0
Quelqu'un peut-il m'expliquer pourquoi les Personnages de propriété est sérialisé correctement mais ne désérialiser?
OK; donc, puisque nous (ou moi, au moins) pensez que le problème est dans le "vrai" code (non illustré); faites-vous quelque chose d'intéressant dans le "set" de l'accesseur de la liste? Ce serait le premier endroit où je regarde.
Non, ils sont tous des propriétés de base avec rien de compliqué dans le d'obtenir ou de définir des accesseurs. Ils se ressemblent tous un peu comme ça: public T PropertyName { get; set; }
Même pour les listes? c'est à dire public List<T> PropName {get;set;}?
Même pour les listes. La seule raison pour laquelle j'ai publics setters sur les listes, bien que, est pour le deserializer. Si les opérateurs privés puis le XmlSerializer déclenche une exception InvalidOperationException de se plaindre au sujet de la lecture-seulement les Caractères de la propriété.
OriginalL'auteur Andy | 2009-05-20
Vous devez vous connecter pour publier un commentaire.
Ne peuvent pas se reproduire; - je obtenir (après la fixation de la plus immédiate de bugs):
Changements:
WriteLine
au lieu deWriteFormat
(qui l'a empêché de compiler)CreateAndSave
de travail):public User() { Characters = new List<Character>(); }
public Character() { Skills = new List<Skill>(); }
Malheureusement, je pense que le problème est dans le code qui est omis.
Heh. Je vais prendre un coup d'oeil un protobuf-net, mais mon but de ce projet était un homme lisible et modifiable format qui pourrait être manipulé avec n'importe quel éditeur de texte de base.
OriginalL'auteur Marc Gravell
Dans le passé, lors de la sérialisation des listes, j'ai utilisé le [XmlArray] et [XmlArrayItem] annotations. Vous pouvez ensuite placer un [XmlIgnore] annotation sur les Caractères de la propriété. Dans votre cas, il ressemblerait à quelque chose comme ceci:
Espère que ça aide.
OriginalL'auteur Dov
Peut-être, au lieu d'un StreamReader, créer un XmlReader, à la place. Aussi, comme une étape de dépannage, vous pouvez essayer votre code existant avec des types explicites (comme ci-dessous) au lieu de "var" déclarations.
EDIT:
Aussi, essayez de le XmlInclude annotation sur votre classe d'Utilisateur.
OriginalL'auteur Dov
Après futzing autour avec le code pendant longtemps, j'ai finalement abandonné l'idée d'utiliser le comportement par défaut de la XmlSerializer.
Toutes les classes héritent de IXmlSerializer et de mettre en œuvre la ReadXml() et WriteXml (). J'espérais vraiment à prendre le paresseux route, mais maintenant que j'ai joué avec IXmlSerializer je me rends compte que ce n'est vraiment pas difficile du tout, et la flexibilité est vraiment sympa.
OriginalL'auteur Andy
Je sais c'est vieux mais j'ai le même problème.
Ce que j'ai trouvé est que si j'ai un objet qui implémente IXmlSerializable dans le graphe (donc l'objet principal que je veux désérialiser ne marche pas implémenter l'interface, mais un objet qu'il met en œuvre), il ruine toute la désérialisation. Les listes ne sont pas désérialiser plus, ni l'objet dont je parle. La sérialisation fonctionne parfaitement.
fait une très bonne observation qui est essentiel si vous avez mis en œuvre IXmlSerializable - assurez-vous que vous avez terminé avec le lecteur.ReadEndElement(); à la fin de votre xml personnalisé lecteur logique
Souhaite que je pourrais upvote vous à la fois, dix fois... Pourquoi sur la Terre, l'article MSDN, j'ai copié le code de verbatim a cette erreur?
OriginalL'auteur alex m
Je voudrais essayer d'utiliser quelque chose comme cela.
Désolé, j'ai fait l'hypothèse.
OriginalL'auteur Chris Watts
J'ai ajouté cet attribut à ma Liste de types et il a travaillé ensuite (il avait le même problème):
Je pense que c'est votre solution.
OriginalL'auteur Brady Moritz
Il pourrait avoir à faire avec la désérialisation de l'enum....depuis il sérialisé comme la chaîne de valeur...pourriez avoir de la difficulté à créer la bonne valeur d'enum pour le personnage. N'ai pas testé cette hypothèse...
-1: il n'y a pas de problème avec l'enum. Je le recommande à l'avenir d'un test, ou ne rien dire.
OriginalL'auteur CSharpAtl