IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++/CLI Discussion :

Petit problème de serialisation


Sujet :

C++/CLI

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2006
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2006
    Messages : 94
    Points : 64
    Points
    64
    Par défaut Petit problème de serialisation
    Bonjour, dans une classe managée j'ai d'autres instances de classes managées. Pour sérialiser et désérialiser ma classe principale, j'appelle directement un Runtime::Serialization::Formatters::Binary::BinaryFormatter.
    Je rajoute l'attribut [Serializable] de l'assembleur au début de chaque déclaration de classe.

    Le problème c'est que lorsque je désérialise l'instance de la classe principale à partir d'un fichier je ne récupère que les variables de l'instance tandis que les instances de classes managées prennent leur valeur par défaut. Est-ce qu'il serait possible de faire le plus simple possible pour contourner ce problème. Est-ce que par exemple il est nécessaire d'utiliser l'interface ISerializable ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    [Serializable]
    public ref class A
    {
    public:
          // ...
    };
     
    [Serializable]
    public ref class B
    {
    public:
          // ...
          A ^pA;
    };
     
    int main(...)
    {
         Runtime::Serialization::Formatters::Binary::BinaryFormatter ^bf;
         bf = gcnew Runtime::Serialization::Formatters::Binary::BinaryFormatter;
         B ^instance;
         String ^filename = "...";
     
         // Serialisation
         IO::StreamWriter ^writer = gcnew IO::StreamWriter(filename);
         bf->Serialize(writer->BaseStream, instance);
         writer->Close();
     
         // Deserialisation
         IO::StreamReader ^reader = gcnew IO::StreamReader(filename);
         instance = (B^) (bf->Deserialize(reader->BaseStream));
         reader->Close();
     
         // A n'est pas initialisé à partir des paramètres déclarés à la sérialisation
         //...
    }

  2. #2
    Rédacteur
    Avatar de nico-pyright(c)
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    6 414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 6 414
    Points : 16 075
    Points
    16 075
    Par défaut
    cela devrait, c'est fait pour, à partir du moment où tes propriétés à sérialiser sont publiques

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 580
    Points
    41 580
    Par défaut
    La présence d'un constructeur désérialisant n'est-elle pas obligatoire pour la sérialisation normale ?
    Ou est-elle seulement nécessaire si on implémente ISerializable ?

  4. #4
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2006
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2006
    Messages : 94
    Points : 64
    Points
    64
    Par défaut
    J'ai oublié un détail !
    En prenant l'exemple ci-dessus la classe A est dans une dll et la classe B dans une autre.
    J'appelle la sérialisation dans mon application.
    C'est donc probable que j'utilise l'interface ISerializable non?

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2006
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2006
    Messages : 94
    Points : 64
    Points
    64
    Par défaut
    La présence d'un constructeur désérialisant n'est-elle pas obligatoire pour la sérialisation normale ?
    Ou est-elle seulement nécessaire si on implémente ISerializable ?
    La question que je pose est alors : "Comment est ce que je crée un constructeur de désérialisation ?".
    (c'est la première fois que j'utilise la sérialisation avant j'utilisais IO pour enregistrer mes instances de classe )

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 580
    Points
    41 580
    Par défaut
    Dans la doc de ISerializable, ils décrivent le constructeur désérialisant: Il prend deux paramètres particuliers, qui contiennent les données sérialisées...

    PS: À ma connaissance, on n'utilise pas ISerializable, on l'implémente.

  7. #7
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2006
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2006
    Messages : 94
    Points : 64
    Points
    64
    Par défaut
    Bon je propose le prototype de code suivant qui ne marche pas mais que vous pourrez sans doute corriger.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    // Dans une dll 1
    [Serializable]
    public ref class A sealed : public ISerializable
    {
    public:
          // ...
          virtual void GetObjectData(SerializationInfo ^info, StreamingContext context)
          {
                // On ajoute les valeurs des instances A à sérialiser ici
                info->AddValue("value", values);
          }
    };
     
    // Dans une Dll 2
    [Serializable]
    public ref class B sealed : public ISerializationSurrogate
    {
    public:
          // ...
          A ^pA;
     
          // Normalement appelée lors de la sérialisation
          virtual void GetObjectData(System::Object ^obj, SerializationInfo ^info, StreamingContext context)
          {
                B ^b = (B^) obj;
                info->AddValue("B::pA", b->pA, A::typeid);
          }
          // Normalement appelée lors de la désérialisation
          virtual System::Object ^SetObjectData(System::Object ^obj, SerializationInfo ^info, StreamingContext context, ISurrogateSelector ^selector)
          {
                B ^b = (B^) obj;
                b->pA = (A^) info->GetValue("B::pA");
                return obj;
          }
     
    };
     
    generic <typename T>
    void fctSerialize(String ^filename, T instance)
    {
    	IO::StreamWriter ^writer = gcnew IO::StreamWriter(filename);
    	Runtime::Serialization::Formatters::Binary::BinaryFormatter ^bf = gcnew Runtime::Serialization::Formatters::Binary::BinaryFormatter;
    	bf->Serialize(writer->BaseStream, instance);
    	writer->Close();
    }
     
    generic <typename T>
    T fctDeserialize(String ^filename, T instance)
    {
    	IO::StreamReader ^reader = gcnew IO::StreamReader(filename);
    	Runtime::Serialization::Formatters::Binary::BinaryFormatter ^bf = gcnew Runtime::Serialization::Formatters::Binary::BinaryFormatter;
    	instance = static_cast <T> (bf->Deserialize(reader->BaseStream));
    	reader->Close();
    	return instance;
    }
     
    // Dans mon appli
    int main(...)
    {
        B ^b; // avec initialisation de l'instance pA
        // ...
        fctSerialize("filename", b);
        // on redémarre l'appli et on désérialise pour le test
        b = fctDeserialize("filename", b);
    }

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 580
    Points
    41 580
    Par défaut
    À ma connaissance, il n'y a pas de méthode SetObjectData() : Il y a le constructeur désérialisant à la place.

  9. #9
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2006
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2006
    Messages : 94
    Points : 64
    Points
    64
    Par défaut
    En fait, je viens de découvrir la question principale du problème :
    si on fait appel à des instances classes définies dans une dll implémentées dans une classe définie dans le code de l'application, est-ce que la sérialisation peut s'effectuer sans que ces instances soient sérialisées sans que leurs valeurs soient corrompues ?

    J'ai essayé de faire une sérialisation classique avec toutes les classes définies avec l'application et tout est sérialisé et désérialisé correctement sauf les instances de classes provenant de dlls...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. un petit problème d'algo
    Par supertramp dans le forum Algorithmes et structures de données
    Réponses: 22
    Dernier message: 12/10/2004, 20h13
  2. Petit problème de décimales !
    Par ridan dans le forum Langage SQL
    Réponses: 5
    Dernier message: 11/09/2004, 21h24
  3. Réponses: 17
    Dernier message: 13/07/2004, 20h37
  4. petit problème premier plan, arrière plan
    Par gros bob dans le forum OpenGL
    Réponses: 4
    Dernier message: 19/04/2004, 12h00
  5. [jointure] Petit problème sur le type de jointure...
    Par SteelBox dans le forum Langage SQL
    Réponses: 13
    Dernier message: 13/02/2004, 18h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo