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

Langage Delphi Discussion :

Sérialisation


Sujet :

Langage Delphi

  1. #1
    Membre à l'essai
    Inscrit en
    Décembre 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 19
    Points : 11
    Points
    11
    Par défaut Sérialisation
    Bonjour

    Voila j'ai un problème pour sauvegarder des classes en delphi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    TClasse1 = class
    private
       attr1 : TClasse2;
    ...
    end;
     
    TClasse2 = class
    private
       attr2 : TClasse1;
    ...
    end;
    Je voudrais sauvegarder les instances de TClasse2.
    J'ai essayé avec WriteComponentResFile et ReadComponentResFile ou WriteComponent et ReadComponent (et en faisant dériver mes classes de TComponent) mais en rechargeant depuis le fichier qui avait été créé, l'attribut attr1 est à nil et je comprends pas pourquoi

    S'il vous plait aidez moi

    Merci d'avance

  2. #2
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Bonjour et bienvenue sur Développez.com

    Ces méthodes n'enregistrent que les propriétés published. Tu dois donc déclarer des propriétés qui pointent vers ces champs privés.

    Si tu ne veux pas permettre de lecture/écriture depuis l'extérieur de l'unité, utilise la méthode DefineProperties et la touche .
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  3. #3
    Membre à l'essai
    Inscrit en
    Décembre 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par sjrd
    Bonjour et bienvenue sur Développez.com

    Ces méthodes n'enregistrent que les propriétés published. Tu dois donc déclarer des propriétés qui pointent vers ces champs privés.

    Si tu ne veux pas permettre de lecture/écriture depuis l'extérieur de l'unité, utilise la méthode DefineProperties et la touche .
    OK Merci bien
    Ca marche avec DefineProperties (et l'aide)

    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
     
    TClasse1 = class(TComponent)
    private
       FAttr1 : TClasse2;
    ...
    published
       Attr1: TClasse2 read FAttr1 write SetAttr1;
    ...
    end;
     
    TClasse2 = class(TComponent)
    private
       FAttr2 : TClasse1;
    ...
    published
       Attr2: TClasse1 read FAttr2 write SetAttr2;
    ...
    end;
    Mais voila quand je mets ca et que j'utilise WriteComponentResFile pour sauvegarder TClasse2, quand je veux relire le fichier l'attribut FAttr2 est toujours à nil et je suis pas arrivé a trouver pourquoi

    Merci d'avance

  4. #4
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Quelles sont les implémentations des SetAttrX ?
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  5. #5
    Membre à l'essai
    Inscrit en
    Décembre 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par sjrd
    Quelles sont les implémentations des SetAttrX ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    procedure SetAttr2(const Value : TClasse1)
    begin
       FAttr2:=Value;
       // ou FAttr2.Assign(Value);
    end;
    Voilà mais j'ai mis un point d'arrêt et ca passe jamais dans la procedure

  6. #6
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Y a-t-il une des deux classes qui est hiérarchiquement supérieure à l'autre, ou si tu préfère qui possède l'autre ?

    Je crois que ceci devrait fonctionner (ne pas oublier de créer une instance de TClasse2 dans TClasse1.Create et la libérer dans TClasse1.Destroy) :
    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
    interface
     
    type
      TClasse2 = classe; // déclaration forward de TClasse2
     
      TClasse1 = class(TPersistent)
      private
        FAttr1 : TClasse2;
        procedure SetAttr1(New : TClasse2);
      published
        property Attr1 : TClasse2 read FAttr1 write SetAttr1;
      end;
     
      TClasse2 = class(TPersistent)
      private
        FAttr2 : TClasse1;
      public
        procedure Assign(Source : TPersistent); override;
      end;
     
    implementation
     
    procedure TClasse1.SetAttr1(New : TClasse2);
    begin
      FAttr1.Assign(New);
      FAttr1.FAttr2 := Self;
    end;
     
    procedure TClasse2.Assign(Source : TPersistent);
    begin
      if Source is TClasse2 then
      begin
        // Assigner correctement
      end else inherited;
    end;
     
    end.
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  7. #7
    Membre à l'essai
    Inscrit en
    Décembre 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Dans ce cas aucune classe dérive de l'autre
    mais si je les fait dériver de TPersistent je peux plus utiliser WriteComponentResFile puisqu'il faut un TComponent

  8. #8
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Citation Envoyé par Osiris1900
    Dans ce cas aucune classe dérive de l'autre
    C'est ce que je craignais : tu as mal compris.
    Je te demande si une des deux classes possède l'autre, pas si l'une dérive de l'autre. Par exemple une lampe possède une ampoule, un fil et une armature, pourtant, ces quatre objets n'ont rien en commun.
    mais si je les fait dériver de TPersistent je peux plus utiliser WriteComponentResFile puisqu'il faut un TComponent[/quote]
    En effet il faut déclarer TClasse1 descendant de TComponent et n'utiliser WriteComponentResFile que sur l'objet de type de TClasse1.
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  9. #9
    Membre à l'essai
    Inscrit en
    Décembre 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par sjrd
    Citation Envoyé par Osiris1900
    Dans ce cas aucune classe dérive de l'autre
    C'est ce que je craignais : tu as mal compris.
    Je te demande si une des deux classes possède l'autre, pas si l'une dérive de l'autre. Par exemple une lampe possède une ampoule, un fil et une armature, pourtant, ces quatre objets n'ont rien en commun.
    mais si je les fait dériver de TPersistent je peux plus utiliser WriteComponentResFile puisqu'il faut un TComponent
    En effet il faut déclarer TClasse1 descendant de TComponent et n'utiliser WriteComponentResFile que sur l'objet de type de TClasse1.[/quote]

    J'ai essayé de faire un code avec des noms un peu plus significatifs que TClasse1 ou FAttr2.

    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
     
      TVoiture = class;
     
      TConducteur = class(TComponent)
      private
        FVoiture : TVoiture;
        FNom : string;
        procedure SetNom(const Value: string);
        procedure SetVoiture(const Value: TVoiture);
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure Initialisation(coul: string; nom: string);
      published
        property Voiture : TVoiture read FVoiture write SetVoiture;
        property Nom : string read FNom write SetNom;
      end;
     
      TVoiture = class(TPersistent)
      private
        FConducteur : TConducteur;
        FCouleur : string;
        procedure SetConducteur(const Value: TConducteur);
        procedure SetCouleur(const Value: string);
      public
        constructor Create(cond: TConducteur; coul: string);
        procedure Assign(Source : TPersistent); override;
      published
        property Conducteur: TConducteur read FConducteur write SetConducteur;
        property Couleur: string read FCouleur write SetCouleur;
      end;
    Donc si j'ai bien compris la classe TConducteur possède la classe TVoiture.

    J'ai alors dans la procédure Initialisation de TConducteur un truc du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    procedure TConducteur.Initialisation(coul, nom: string);
    begin
      FNom:=nom;
      FVoiture:=TVoiture.Create(Self, coul);
    end;
    Quand je veux sauvegarder une instance de TConducteur, je fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    WriteComponentResFile(FileName, conducteur);
    Et pour relire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    conducteur:=ReadComponentResFile(FileName, cond1) as TConducteur;
    Et si cond1 est à nil, conducteur.Voiture est aussi à nil. Alors j'ai essayé en créant et en initialisant cond1 et la ça marche.
    Pourquoi si cond1 est égal à nil ça marche pas : (d'ailleurs ce paramètre est mis à nil dans l'aide de delphi)

  10. #10
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Citation Envoyé par Osiris1900
    Donc si j'ai bien compris la classe TConducteur possède la classe TVoiture.
    En effet.
    Citation Envoyé par Osiris1900
    J'ai alors dans la procédure Initialisation de TConducteur un truc du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TConducteur.Initialisation(coul, nom: string);
    begin
      FNom:=nom;
      FVoiture:=TVoiture.Create(Self, coul);
    end;
    Non c'est le constructeur Create qui doit faire ça (sans oublier le inherited) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    constructor TConducteur.Create(coul, nom : string);
    begin
      inherited Create(nil);
      FNom := nom;
      FVoiture := TVoiture.Create(Self, coul);
    end;
    Citation Envoyé par Osiris1900
    Quand je veux sauvegarder une instance de TConducteur, je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WriteComponentResFile(FileName, conducteur);
    Et pour relire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    conducteur:=ReadComponentResFile(FileName, cond1) as TConducteur;
    C'est cela même.
    Citation Envoyé par Osiris1900
    Et si cond1 est à nil, conducteur.Voiture est aussi à nil. Alors j'ai essayé en créant et en initialisant cond1 et la ça marche.
    Pourquoi si cond1 est égal à nil ça marche pas : (d'ailleurs ce paramètre est mis à nil dans l'aide de delphi)
    Là je ne te suis pas...
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  11. #11
    Membre à l'essai
    Inscrit en
    Décembre 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Là je ne te suis pas...
    Je veux dire que quand on fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    conducteur:=ReadComponentResFile(FileName, nil) as TConducteur;
    conducteur.Voiture vaut nil

    Mais si on fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    cond1:=TConducteur.Create(Self);
    cond1.Initialisation('', ''); // ou n'importe quelles autres valeurs
    conducteur:=ReadComponentResFile(FileName, cond1) as TConducteur;
    conducteur.Voiture est égal a la valeur attendue

    Voila j'espère avoir été un peu plus clair

  12. #12
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Citation Envoyé par A propos de WriteComponentResFile, l'aide Delphi
    Appelez ReadComponentResFile pour créer un composant et ses enfants depuis leur représentation dans un fichier de ressources Windows.

    Le paramètre FileName est le nom du fichier de ressources compilées qui contient le composant.

    Le paramètre Instance est une instance du type du composant qui doit être lu. Créez une instance du type d'objet approprié et appelez ReadComponentResFile pour lire ses propriétés. Si Instance est à nil (Delphi) ou NULL (C++), la classe objet est lue depuis la ressource. Avant de transmettre un paramètre Instance à (Delphi) ou NULL (C++), toutes les classes lues doivent avoir été recensées à l'aide de la routine RegisterClass ou RegisterClasses.

    ReadComponentResFile renvoie une instance du composant qui a été lu dans le fichier de ressources.
    Donc, si tu veux pouvoir passer nil à la fonction, tu dois faire ceci dans les initialization/finalization de l'unité qui déclare les classes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    initialization
      RegisterClass(TConducteur);
    finalization
      UnregisterClass(TConducteur);
    end.
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  13. #13
    Membre à l'essai
    Inscrit en
    Décembre 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par sjrd
    Donc, si tu veux pouvoir passer nil à la fonction, tu dois faire ceci dans les initialization/finalization de l'unité qui déclare les classes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    initialization
      RegisterClass(TConducteur);
    finalization
      UnregisterClass(TConducteur);
    end.
    Oui je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    initialization
       RegisterClasses([TConducteur, TVoiture]);
    finalization
       UnRegisterClasses([TConducteur, TVoiture]);
    et au moment du ReadComponentResFile(FileName, nil) il fait une erreur EReadError
    "Error reading TConducteur.Voiture.Couleur
    Invalid property path"

  14. #14
    Membre à l'essai
    Inscrit en
    Décembre 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    OK c'est bon j'ai compris pourquoi.
    Merci bien pour tout

  15. #15
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Un petit ?
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  16. #16
    Membre à l'essai
    Inscrit en
    Décembre 2004
    Messages
    19
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    oui

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

Discussions similaires

  1. [Sérialisation] d'objets de types différents
    Par Amnesiak dans le forum Général Java
    Réponses: 3
    Dernier message: 08/12/2004, 22h28
  2. [Sérialisation] StackOverFlowError levée
    Par ptitjack dans le forum Général Java
    Réponses: 9
    Dernier message: 04/11/2004, 13h27
  3. [Serializable][image] Sérialiser une image
    Par Galima dans le forum Graphisme
    Réponses: 7
    Dernier message: 01/07/2004, 18h12
  4. Sérialisation avec sockets
    Par sebi77 dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 03/05/2004, 20h24
  5. SGBD ou sérialisation
    Par tiboleo dans le forum Décisions SGBD
    Réponses: 3
    Dernier message: 07/10/2003, 16h18

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