Sérialiser/désérialiser plusieurs classes [Résolu]

Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
- - Dernière réponse : Whismeril
Messages postés
12426
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
19 décembre 2018
- 16 juil. 2012 à 18:21
Bonjour,

débutant en C# j'ai trouvé un tuto sympa pour sérialiser en XML une classe et toutes ses propriétés.
exemple type: une listview affichant des contacts (nom, prenom, tel, adresse)
une list de contacts et hop on sérialise l'objet contact_list

dans mon cas précis j'utilise plusieurs classes, dans différents form
et je souhaite lorsque l'utilisateur ferme l'appli pouvoir sauvegarder toutes les données
et lui permettre de les charger au démarrage.
il faut donc que je sérialise différentes classes .
comment est ce possible? et en un seul fichier XML pour éviter de serialiser 5/6 fois.
d'ailleurs est-ce possible?

merci

 
Afficher la suite 

Votre réponse

20/23 réponses

Meilleure réponse
Messages postés
12426
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
19 décembre 2018
3
Merci
Pardon sur le dernier post je ne t ai pas remis le bon lien, et je ne peux pas le faire depuis ma tablette.
Je parlais du lien que je t'ai donné à 13:31.

Le fait des serialiser des objets n'est pas lié aux winforms. Je t accordes que ce code est flou et avoir un peu pataugé au début.

Si tu veux serialiser des données de classe À et des données de classe B, l'idée est de créer une classe C, qui aura en propriété une liste de A et une liste de B, ainsi quand tu sérializes C, tu sérializes ta liste de A et ta liste de B.

Sinon, regarde les discussions sur linq, vu que tu décris pas par pas le format du fichier tu faits ce que tu veux.

Je tâcherai de t'aider plus à mon retour mardi

Whismeril

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 105 internautes nous ont dit merci ce mois-ci

Commenter la réponse de Whismeril
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
0
Merci
Aucune aide? peut-être ai-je mal exprimé mon soucis?

 :(
Commenter la réponse de LaTatadu91
Messages postés
1540
Date d'inscription
lundi 26 mai 2003
Dernière intervention
1 août 2013
0
Merci
Salut,

la sérialisation XML est un peu fastidieuse en C#, par contre une fois codée le load/save est très pratique à l'usage. Pour connaitre le détail de sa mise en place je te laisse regarder sur la MSDN.

Pour ce qui est de concentrer les données en un seul fichier, il te suffit de créer une classe, sérialisable également, qui contient la référence de chacune de tes instances d'objets. Tu fais ces références lors de la clôture de l'appli puis tu sérialises la classe.

Bon dev
Commenter la réponse de cs_jopop
Messages postés
12426
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
19 décembre 2018
0
Merci
Bonjour
débutant en C# j'ai trouvé un tuto sympa pour sérialiser en XML une classe et toutes ses propriétés


Peux tu mettre le code que tu utilises, il y a "50" façon de serialiser et la réponse peut dépendre de la manière dont tu foncionnes déjà.

Ce code par exemple montre une utilisation de xml serilazer, si je me souvient bien il creer une classe configuration dans laquelle il y a plusieures List<T> des différentes classe à serializer.

Dans cette discussion, nous avons comparé plusieurs méthode et dérivé sur des essais avec Linq (ce que j'utilise principalement aujourd'hui), là un autre exempleavec Linq

Whismeril
Commenter la réponse de Whismeril
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
0
Merci
Ok, je vois, merci.

par contre je dois avoir un problème lors de ma conception de mon appli.
j'utilise un form à part pour la gestion utilisateur (save/load/etc...)
j'arrive à sauvegarder une classe de mon form1 (pour test)
mais dans form1(utilisation des données/affichage dans des grid/textbox) je n'arrive pas à accéder à l'instance de ma classe déclarée dans mon form (save/load)
j'ai un problème de portée en gros.




 
Commenter la réponse de LaTatadu91
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
0
Merci
Whismeril, je me suis basé sur ce tuto.-->
Tapez le texte de l'url ici.



 
Commenter la réponse de LaTatadu91
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
Commenter la réponse de LaTatadu91
Messages postés
12426
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
19 décembre 2018
0
Merci
Le lien avait marché ;-).
Cet exemle utilise xmlserializer, donc tu peux jetter une oeuil au premier code que je t'ai indiqué.

Pour acceder aux données d'une classe à une autre (les formulaires sont des cas particuliers de classes), la meilleure soltuion est de passer des paramètres de l'un vers l'autre:



Whismeril
Commenter la réponse de Whismeril
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
0
Merci
je check ça et reviens vers toi si je m'en sors pas!

encore merci

 
Commenter la réponse de LaTatadu91
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
0
Merci
Jopop !
pour la classe ("gloable") avec l'instance de tous mes objets.
Tu dis qu'il faut faire références lors de la cloture , comment?
aussi lors de l'ouverture du fichier et de la désérialisation, comment renseigner mes objets et les utiliser dans leur form respectifs à partir de la classe ("gloable") ?

merci
 
Commenter la réponse de LaTatadu91
Messages postés
12426
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
19 décembre 2018
0
Merci
Pour faire des actions à la cloture de l'application, il faut mettre le code dans l'évement FormClosing du formulaire principal.

comment renseigner mes objets et les utiliser dans leur form respectifs à partir de la classe ("gloable") ?
, tu devrais vraiment regarder ce code

Whismeril
Commenter la réponse de Whismeril
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
0
Merci
Oui j'ai vu ce code, je le trouve pas super clair.
et comme il n'utilise pas de winforms c'est moins facile de s'y retrouver...
 
Commenter la réponse de LaTatadu91
Messages postés
12426
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
19 décembre 2018
0
Merci
Bonjour

as tu avancé?


Whismeril
Commenter la réponse de Whismeril
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
0
Merci
salut!

Désolé je n'ai pas vraiment pu avancer, je suis en formation Admin SQL (rien à voir)
toute la semaine.
Mais j'y ai un peu pensé.
Je pense vraiment que la sérilisation devrait marcher (j'ai deja test sur une seule de mes classes pour voir)
et ca marche
par contre j'ai réussi à deserialiser C. ca marchait aussi mais dans le form C(par rapport à ton exemple)
je n'arrivais pas à retrouver les données deserialisées dans mon form B(classeB)



 
Commenter la réponse de LaTatadu91
Messages postés
12426
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
19 décembre 2018
0
Merci
Bonjour,
je ne suis pas sur de bien comprendre, c'est les formulaires que tu serializes ou les données affichées dans ces formaulires?


Whismeril
Commenter la réponse de Whismeril
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
0
Merci
Excuse moi j'avoue que c'est pas super clair. j'ai écrit à toute vitesse hier.
Je sérialise des classes de données qui sont affichées dans des form spécifique
donc
j'ai un form A qui affiche différents controls: listview, textbox etc...
une ou des classes y sont associées

dans un form B, je fais une sérialisation de la classe A -->sur evenement click d'un bouton "save"

Ici tout roule (avec une seule classe) j'ai mon fichier XML que j'ai relu et qui semble correct.
Par contre tjrs à partir du form B-->click bouton "load"
je deserialise ma classe A (au niveau du form B pour le code) --> ça marche


mais lorsque j'affiche mon Form A , je ne retrouve pas mes données deserialisées ou lues.
j'affiche la classe A de base.
Je n'arrive pas a ccéder à la classe définie dans le form B

est ce plus clair? :)

merci pour ton support

 
Commenter la réponse de LaTatadu91
Messages postés
12426
Date d'inscription
mardi 11 mars 2003
Statut
Contributeur
Dernière intervention
19 décembre 2018
0
Merci
Je pense avoir compris.

Quand tu modifies tes données de classe A dans la Form B, les modifcations ne sont pas prises en compte dans le formulaire A.

Pour que cela ssoit possible il y a plusieures conditions, d'abord le jeux de données utilisé doit être le même partout.

Si dans Form A tu as une List<T> maListeA dans laquelle il y a les données et que dans Form B, il y a maListeB, pour que le jeux de donnée soit le même il doit avoir été passé en paramètre d'une Form à l'autre.
Dans ce cas c'est le contenant des données qui est passé et les données
manipulées de partes et d'autres sont les mêmes. (c'est un peu comme le passage de reférence en C/C++).
Il me semble que tu deserializes les données dans chaque formulaires donc ton contenant est différent et aux bout d'un moment les données aussi.

D'autre part, il te faudra peut-être rafraichir le FormA quand les données sont modifiées sur FormB, pour ça une solution est de creer un événement dans FormB et quand tu cree une instance de FormB dans FormA tu t'abonnes à cet événement. Dans la méthode abonnée tu écris le code de rafraichissement des données. C'est comme quand tu écris le code "Click" d'un bouton, sauf que le déclencheur est sur un autre formulaire. Il y a ce code qui m'a servi au début




Whismeril
Commenter la réponse de Whismeril
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
0
Merci
En fait c'est encore plus simple que ça je pense ...
car j'affiche un seul form à chaque fois, impossible pour l'utilisateur d'ouvrir plusieurs fenetres.
en gros l'utilisateur utilise cet outil, qui fait différents calculs en fonction des données
rentrées. puis il les valide
et en allant sur la page de "gestion de fichiers" il peut sauvegarder les données entrées et le sorties.
comme ça il peut nevoyer ses resultats à une autre personne qui lui aura plus qu'a charger ce fichier.

donc comme jte disais, je pense avoir un problème de portée de mes classes.

je n'ai pas mon code avec moi là.
mais le mieux serait peut etre que tu vois le code directement, a mon avis tu comprendrais bien mieux

 
Commenter la réponse de LaTatadu91
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
0
Merci
Donc, pour mon soucis, voilà le code que j'ai écris: je pense que ça t'aidera a mieux voir ce dont je parle:
fichier User Management.cs

   public partial class ucUserMng : BaseModule {

        WasteGasComposition compoWG;

     
        public ucUserMng()
        {
            InitializeComponent();
            compoWG = new WasteGasComposition();
        }

        private void simpleButton1_Click(object sender, EventArgs e) //open file
        {
            using (OpenFileDialog fileOpen = new OpenFileDialog())
            {
                fileOpen.Filter = "Fichier xml(*.xml)|*.xml";
                fileOpen.InitialDirectory = @"c:";

                if (fileOpen.ShowDialog() == DialogResult.OK)
                {
                    compoWG = compoWG.Load(fileOpen.FileName);
                    AppConst.FileLoaded = true;
                }
            }
        }

        private void simpleButton2_Click(object sender, EventArgs e) // save file
        {
            SaveFileDialog fileSave = new SaveFileDialog();
            fileSave.Filter = "Fichier xml(*.xml)|*.xml";
            if (fileSave.ShowDialog() == DialogResult.OK)
            {
                compoWG.Save(fileSave.FileName);
            }
        }
    }

là c'est le code pour la gestion des fichiers à charger ou sauvegarder.
J'y décalre ma classe "WasteGasComposition " et l'instancie dans le constructeur.
jusqu'ici je pense que ça roule.

ensuite j'ai la définition de ma classe(en fait toutes mes classes) dans un fichier data.cs
 [Serializable]
    public class WasteGasComposition
    {
        public static double o2;
        public static double co2;
        public static double h2o;
        public static double so2;
        public static double n2;
        public static double ar;

        public double O2
        {
            get { return o2; }
            set { o2 = value; }
        }
        public double CO2
        {
            get { return co2; }
            set { co2 = value; }
        }
        public double H2O
        {
            get { return h2o; }
            set { h2o = value; }
        }
        public double SO2
        {
            get { return so2; }
            set { so2 = value; }
        }
        public double N2
        {
            get { return n2; }
            set { n2 = value; }
        }
        public double Ar
        {
            get { return ar; }
            set { ar = value; }
        }

        public void Save(string filename)
        {
            FileStream file = File.Open(filename, FileMode.OpenOrCreate);
            XmlSerializer serializer = new XmlSerializer(typeof(WasteGasComposition));
            serializer.Serialize(file, this);
            file.Close();
        }

        public WasteGasComposition Load(string filename)
        {
            FileStream file = File.Open(filename, FileMode.Open);
            XmlSerializer serializer = new XmlSerializer(typeof(WasteGasComposition));
            WasteGasComposition uneCompo = (WasteGasComposition)serializer.Deserialize(file);
            file.Close();
            return uneCompo;
        }
    }

là encore je pense que c'est bon... définition des propriétes de la classe et des fonctions save et load.

Puis dans mon form d'affichage des données j'ai ça et c'est là que ça bloque:
public partial class ucDesignPoint : BaseModule {
      

        public ucDesignPoint()
        {
            InitializeComponent();
        }

        internal override void InitModule(IDXMenuManager manager, object data)
        {
            base.InitModule(manager, data);
            InitData();
            
        }

        void InitData()
        {
            // Default data - initialize data
            float O2 = 2.49f;
            float CO2 = 8.50f;
            float H2O = 16.23f;
            float SO2 = 0.00f;
            float N2 = 72.77f;
            float Ar = 0.00f;

            if (AppConst.FileLoaded == false) // file not loaded Init data with default data
            {
                textEditO2.Text = O2.ToString();
                textEditCO2.Text = CO2.ToString();
                textEditH2O.Text = H2O.ToString();
                textEditSO2.Text = SO2.ToString();
                textEditN2.Text = N2.ToString();
                textEditAr.Text = Ar.ToString();
            }
            else // Init data with data in XML file
            {
                textEditO2.Text = WasteGasComposition.o2.ToString();
                textEditCO2.Text = WasteGasComposition.co2.ToString();
                textEditH2O.Text = WasteGasComposition.h2o.ToString();
                textEditSO2.Text = WasteGasComposition.so2.ToString();
                textEditN2.Text = WasteGasComposition.n2.ToString();
                textEditAr.Text = WasteGasComposition.ar.ToString();
            }

la partie qui nous interresse est dans le else: là j'utilise une autre instance de la classe sauvegardée
du coup forcément ça ne marche pas, mais si je veux utiliser l'instance utilisée dans mon form de sauvegarde à savoir : CompoWG, elle n'est pas reconnue....

voilà!
une fois que ça marchera, je pourrais faire ce que tu m'as dit : faire une classe globale qui liste toutes les classes que je veux sauvegardées, et sérialiser cette classe globale.
Je fais étape par étape...

merci encore de ton aide.
 
Commenter la réponse de LaTatadu91
Messages postés
968
Date d'inscription
jeudi 20 mai 2004
Dernière intervention
26 avril 2013
0
Merci
c'est bon j'ai trouvé:
ucUserMng.compoWG

alors j'aiavais deja testé ça la semaine dernière , ça me paraissait logique mais je pense qu'intellisense était dans les choux...

a priori ça va marcher, j'ai plus qu'à créé ma classe globale ^^
jte tiens au jus si c'est bon
et je valide ta réponse
 
Commenter la réponse de LaTatadu91

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.