8
votes

C # - Comment xml désériorize objet lui-même?

public class Options
    {
        public FolderOption FolderOption { set; get; }

        public Options()
        {
            FolderOption = new FolderOption();
        }


        public void Save()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Options));
            TextWriter textWriter = new StreamWriter(@"C:\Options.xml");
            serializer.Serialize(textWriter, this);
            textWriter.Close();
        }

        public void Read()
        {
            XmlSerializer deserializer = new XmlSerializer(typeof(Options));
            TextReader textReader = new StreamReader(@"C:\Options.xml");
            //this = (Options)deserializer.Deserialize(textReader);
            textReader.Close();

        }
    }
}
I managed to Save without problem, all members of FolderOption are deserialized. But the problem is how to read it back? The line -  //this = (Options)deserializer.Deserialize(textReader); won't work. Edit: Any solution to this problem? Can we achieve the same purpose without assigning to this? That is deserialize Options object back into Option. I am lazy to do it property by property. Performing on the highest level would save of lot of effort.

0 commentaires

7 Réponses :


0
votes

voir XMLSerializer.Desérialize Méthode : Vous pouvez créer une méthode statique comme suit: xxx

ce qui précède peut être appelé comme suit: xxx < / p>


2 commentaires

1) Veuillez lire sa question plus attentivement. 2) -1 Pour ne pas utiliser de blocs "en utilisant".


Vous avez toujours besoin d'une utilisation autour de la xmlreader.



5
votes

Un objet ne peut pas désérialiser elle-même, par définition: il existe déjà, et la désérialisation crée une nouvelle instance du type.

Il est parfois logique de créer une nouvelle instance vide d'une classe, puis remplissez-la avec des informations. apporté de XML. L'instance pourrait également être "presque vide". Vous pouvez le faire, par exemple, afin de charger les préférences des utilisateurs ou en général, de régler l'instance à la manière dont elle était utilisée. L'état "vide" ou "presque vide" de l'instance serait un état valide pour la classe: il ne saurait tout simplement pas savoir quel état il avait l'habitude d'être persisté.


En outre, je vous recommande d'entrer dans l'habitude de mettre en œuvre des blocs "à l'aide": xxx

Cela garantira que les textreaders sont éliminés même si une exception est lancée. C'est pourquoi les appels proches ne sont plus nécessaires.


0 commentaires

11
votes

Cela fonctionnera si votre type d'options est une structure, comme vous pouvez altérer une structure elle-même.

Si les options sont une classe (type de référence), vous ne pouvez pas attribuer à l'instance actuelle d'un type de référence avec dans ce cas. Vous suggère d'écrire une classe d'assistance et de mettre vos méthodes de lecture et d'enregistrement là-bas, telles que ceci xxx

puis consommez-le de votre appelant, de lire et de sauvegarder des objets, à la place de essayant de la classe. xxx

et mettre le xmlSerializerhelper dans l'espace de noms de votre util, il est réutilisable et fonctionnera avec n'importe quel type.


6 commentaires

-1 Pour ne pas mettre en œuvre des blocs "en utilisant", et pour ne pas utiliser de génériques.


Utilisation (xmlSerializer désérialiszer = nouveau xmlSerializer (_type)) ne fonctionne pas. XMLSerializer n'a pas mis en œuvre Idisposable. La bonne devrait être comme ce que la réponse de John, mettant xmlsérialisateur en dehors de l'utilisation du bloc.


Oups, oublié un instant que XmlSerializer n'a pas mis en œuvre Idisposable, corrigé :)


Merci pour la mise à jour. Au moins maintenant, je sais ce que John signifie par "n'utilisant pas de génériques".


L'ensemble du point d'utilisation des génériques est d'éviter de coulée. // dans la classe d'assistance annulation publique sauvegarde (chemin de chaîne, t @Object); public t lire (chemin de cordes); Rendez le résultat; // en classe appelante obj = helper.read ("Yourpath"); // pas de casting requis


Oui, maintenant j'ai écrit que dans l'IDE et que je m'assurait qu'il s'agisse de la compilation, lol;)



20
votes

Construisez votre .Read () comme une fonction statique qui renvoie l'objet de lecture: xxx

puis changez votre code d'appel aussi que quelque chose comme ça: xxx

vous faites quelque chose comme ceci: xxx

La belle différence est qu'il est impossible de disposer d'un objet d'options qui n'a pas de données derrière elle.


2 commentaires

Je suis d'accord, cet imo est la solution la plus propre qui répond à la question.


Je ne peux pas commenter pour les autres, mais cela correspond au meilleur projet actuel ... très soigné.



1
votes

Je suis allé pour cette approche (en VB) xxx

Je peux alors utiliser quelque chose comme ceci: xxx

et appelez-le comme ceci: xxx

ou même mieux (si j'ajoute le constructeur nécessaire): xxx

Il semble beau et propre Pour moi et fonctionne bien dans ma situation.

acclamations


0 commentaires

2
votes

Je pense que le moyen le plus simple de sérialiser et de désérialiser un objet est d'utiliser une classe statique avec les deux méthodes suivantes. Nous avons également besoin d'une classe nommée StringWriterWithecoding pour définir le codage de la chaîne XML, car la propriété de codage de la classe StringWriter standard est réadonnée. (trouvé ici: http: // devrogroj20 .blogspot.com / 2008/02 / ECRIDE-XML-OUTF-8-CODING-UTILISATION.HTML )

//serialize
MyClass myClass = new MyClass();
string xml = GenericXmlSerializer.Serialize<MyClass>(myClass, Encoding.Unicode);

//deserialize
MyClass myClass2 = GenericXmlSerializer.Deserialize<MyClass>(xml);


0 commentaires

2
votes

Je suis fan de méthodes d'extension, donc j'utilise cela toujours:

[XmlElement("NameOfTheElementYouWant")] 
[XmlAttribute("NameOfTheAttributeYouWant")]
[XmlText]


0 commentaires