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# Discussion :

Serialization et déserialization d'objets hérités


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    208
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 208
    Par défaut Serialization et déserialization d'objets hérités
    Bonjour,

    Merci d'avance pour votre aide

    Soit une classe de base BaseClass, et deux classes A et B qui héritent de BaseClass
    J'aimerai que BaseClass implémente les méthodes de sérialisation et de déserialisation suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public virtual void Save(XmlWriter xwWriter)
    {
           XmlSerializer xsSerializer = new XmlSerializer(this.GetType());
           xsSerializer.Serialize(xwWriter, this);
    }
     
    public virtual void Load(XmlReader xrReader)
    {
            XmlSerializer xsSerializer = new XmlSerializer(this.GetType());
            this = (this.GetType())xsSerializer.Deserialize(xrReader);
    }
    La méthode de serialisation fonctionne très bien.
    Mais forcément la méthode de déserialisation n'est pas correcte car le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this = (this.GetType())xsSerializer.Deserialize(xrReader);
    est interdit.

    Avez vous une idée pour faire quelque chose d'équivalent, ou est ce que je dois implémenter la méthode Load sur toutes les classes qui héritent de BaseClass

  2. #2
    Membre expérimenté
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Par défaut
    Avec une méthode statique par exemple. Quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public static T Load<T>(XmlReader xrReader) where T : BaseClass
    {
        XmlSerializer xsSerializer = new XmlSerializer(typeof(T));
        return (T)xsSerializer.Deserialize(xrReader);
    }
    Et pour charger
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonObjet objet = BaseClass.Load<MonObjet>(reader);
    Ou sinon tu complètes avec une méthode que devront implémenter les classes enfants pour initialiser leurs champs. Quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public void Load(XmlReader xrReader)
    {
        XmlSerializer xsSerializer = new XmlSerializer(this.GetType());
        BaseClasse objet = (BaseClasse)xsSerializer.Deserialize(xrReader);
        CopyFrom(objet)
    }
     
    // Recopie les valeurs de objet dans les champs de l'instance.
    protected abstract CopyFrom(BaseClass objet);
    Mais ça fait faire plus de travail.

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    826
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2006
    Messages : 826
    Par défaut
    en effet tu ne peux pas faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this = (this.GetType())xsSerializer.Deserialize(xrReader);
    car tu taperais sur l'instance en cours. Ce mécanisme va créer une nouvelle instance.

    J'y vois deux solutions :
    - soit utiliser un objet intermédiaire et faire la copie après ; c'est bof et en plus tu perds l'avantage de ton héritage.
    - soit tu réaliser une méthode statique et générique pour la déserialization. Tu peux d'ailleurs et mettre le Save aussi afin d'avoir une classe dont l'unique responsabilité est la sérialization.

    ps : mince j'ai été trop lent ...

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    208
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 208
    Par défaut
    Merci pour votre aide.

    Voilà la solution que j'ai implémenté:
    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
     
    public void Load(XmlReader xrReader) 
    {
    	// Get the type and the properties
    	Type tType = this.GetType();
    	PropertyInfo[] piProperties = tType.GetProperties();
    	// Create a serializer
    	XmlSerializer xsSerializer = new XmlSerializer(tType);
    	// Deserialize
    	BaseClass oCurrentObject = (BaseClass)xsSerializer.Deserialize(xrReader);
    	// For each property of T
    	foreach(PropertyInfo piProperty in piProperties)
    	{
    		if(piProperty.CanWrite)
    		{
    			// Get the value
    			object oValue = piProperty.GetValue(oCurrentObject, null);
    			// Set the property value
    			piProperty.SetValue(this, oValue, null);
    		}
    	}
    }
    PS: si vous avez des infos sur le fonctionnement de la méthode GetProperties, je suis preneur.... Par ce que à chaque fois que j'utilise un paramètre BindingFlags, cela ne fonctionne pas
    dans le cas présent j'ai essayé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tType.GetProperties(BindingFlags.SetProperty);
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty);
    ni l'un ni l'autre ne me renvoie les propriétés ayant un set

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    826
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2006
    Messages : 826
    Par défaut
    ne n'est pas possible de les retrouver de cette façon. il faut récupérer toutes les propriétés et le traiter une à une (via propertyinfo http://msdn.microsoft.com/en-us/libr...pertyinfo.aspx).

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    208
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 208
    Par défaut
    Dans ce cas à quoi sert le paramètres BindingFlags?

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    826
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juin 2006
    Messages : 826
    Par défaut
    Si on se réfère à http://msdn.microsoft.com/en-us/libr...dingflags.aspx, il semble que la valeur SetProperty est utilisée pour l'affectation de valeur.

    A première vue, il faut utiliser le nom qui est ou de la forme set_MaProp ou get_MaProp, mais ça me semble bizarre qu'il n'y ait pas d'autre moyen.

Discussions similaires

  1. [Question] PL/SQL et la gestion des objets hérités
    Par trouiller dans le forum PL/SQL
    Réponses: 2
    Dernier message: 23/04/2010, 10h35
  2. Réponses: 3
    Dernier message: 18/11/2009, 16h48
  3. Sérialisation d'objet hérité
    Par ppphil dans le forum C#
    Réponses: 6
    Dernier message: 12/01/2009, 11h36
  4. Réponses: 5
    Dernier message: 27/11/2008, 09h54
  5. [JGoodies ] Utiliser un objet hérité pour le binding
    Par mush_H dans le forum Interfaces Graphiques en Java
    Réponses: 2
    Dernier message: 18/09/2007, 09h02

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