Sérialiser/désérialiser plusieurs classes

Résolu
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 - 4 juil. 2012 à 15:42
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 - 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

 

23 réponses

Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 656
6 juil. 2012 à 20:02
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
3
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
5 juil. 2012 à 09:43
Aucune aide? peut-être ai-je mal exprimé mon soucis?

 :(
0
cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
5 juil. 2012 à 11:25
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
0
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 656
5 juil. 2012 à 11:56
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
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
5 juil. 2012 à 11:56
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.




 
0
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
5 juil. 2012 à 11:59
Whismeril, je me suis basé sur ce tuto.-->
Tapez le texte de l'url ici.



 
0
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
5 juil. 2012 à 12:01
0
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 656
5 juil. 2012 à 13:31
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
0
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
5 juil. 2012 à 13:49
je check ça et reviens vers toi si je m'en sors pas!

encore merci

 
0
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
5 juil. 2012 à 14:51
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
 
0
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 656
5 juil. 2012 à 15:29
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
0
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
6 juil. 2012 à 13:06
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...
 
0
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 656
10 juil. 2012 à 12:21
Bonjour

as tu avancé?


Whismeril
0
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
10 juil. 2012 à 13:26
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)



 
0
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 656
11 juil. 2012 à 13:13
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
0
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
11 juil. 2012 à 13:20
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

 
0
Whismeril Messages postés 19027 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 24 avril 2024 656
11 juil. 2012 à 14:06
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
0
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
11 juil. 2012 à 14:26
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

 
0
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
16 juil. 2012 à 11:29
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.
 
0
LaTatadu91 Messages postés 968 Date d'inscription jeudi 20 mai 2004 Statut Membre Dernière intervention 26 avril 2013 1
16 juil. 2012 à 11:47
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
 
0
Rejoignez-nous