Soap Serialiser générique et Liste<T>

Description

Je me suis apercu que la serialisation de liste générique avec un SoapFormater n'était pas pris en charge.
J'ai donc cherché a détourné le problème.

Problème rencontré

public class AxSerialiser<T>
{
    public static void SoapSerialiseToFile(string _Path, T _Object)
    {
        try
        {
            FileStream _FileStream = new FileStream(_Path, FileMode.OpenOrCreate, FileAccess.Write);
            SoapFormatter soapFormatter = new SoapFormatter();
            soapFormatter.Serialize(_FileStream, _Object);
            _FileStream.Close();
        }
        catch (Exception e)
        {
            MessageBox.Show("Failed SoapSerialiseToFile.rnReason : " + e.Message, "WARNING", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }
}

Ceci utilisé avec un objet contenant une Liste<T> renvoie une erreur.
J'ai donc implémenté la classe suivante.

Solution

/// <summary>
/// Classe générique fournissant une System.Collections.Generic.List
/// et l'implementation de ISerializable permettant de la sérialiser a l'aide d'un SoapFormatter.
/// </summary>
/// <typeparam name="T">The type of elements in the list.</typeparam>
[Serializable]
public abstract class GenericListClassObject<T> : ISerializable
{
    /// <summary>
    /// La Liste fournie par notre classe
    /// </summary>
    List<T> _List = new List<T>();
    
    /// <summary>
    /// La propriété marquée comme "virtual".
    /// c'est pratique pour voir de quoi on parle dans la classe dérivée.
    /// </summary>
    public virtual List<T> List
    {
        get { return _List; }
        set { _List = value; }
    }
    
    /// <summary>
    /// Le constructeur
    /// </summary>
    public GenericListClassObject()
    {

    }
    
    #region Membres de ISerializable
    /// <summary>
    /// Le "déconstructeur" utilisé pour la sérialisation.
    /// </summary>
    /// <param name="info">Stores all the data needed to serialize or deserialize an object.</param>
    /// <param name="context">Describes the source and destination of a given serialized stream, and provides an additional caller-defined context.</param>
    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        ///On vas tout simplement transformer notre Liste de 'T' en un tableau de 'T'
        ///et l'ajouter au SerializationInfo.
        info.AddValue("_List", _List.ToArray(), typeof(T[]));
        Type t = this.GetType();
        info.AddValue("TypeObj", t);
    }

    /// <summary>
    /// Le constructeur Utilisé pour la désérialisation
    /// </summary>
    /// <param name="si">Stores all the data needed to serialize or deserialize an object.</param>
    /// <param name="context">Describes the source and destination of a given serialized stream, and provides an additional caller-defined context.</param>
    public GenericListClassObject(SerializationInfo si, StreamingContext context)
    {
        ///On récupere notre tableau d'objets 'T' dans SerializationInfo.
        T[] tmp = (T[])si.GetValue("_List", typeof(T[]));
        ///On remet les elements du tableau dans notre Liste.
        _List = new List<T>((IEnumerable<T>) tmp);
    }

    #endregion
}

On peut donc utiliser une classe telle que celle ci:

/// </summary>
[Serializable]
public class Hotel : GenericListClassObject<Chambre>,ISerializable
{
    /// <summary>
    /// Champ 'nom', le nom de notre hotel
    /// </summary>
    string nom = "Hotel Bel air";
    
    /// <summary>
    /// Propriéte 'Nom'.
    /// </summary>
    public string Nom
    {
        get { return nom; }
        set { nom = value; }
    }
    
    /// <summary>
    /// Propriéte List, celle ci est fournie par notre classe 'GenericListClassObject'.
    /// </summary>
    public override List<Chambre> List
    {
        get {return base.List;}
        set {base.List = value;}
    }
    
    /// <summary>
    /// Le constructeur Utilisé pour la désérialisation
    /// </summary>
    /// <param name="si">Stores all the data needed to serialize or deserialize an object.</param>
    /// <param name="context">Describes the source and destination of a given serialized stream, and provides an additional caller-defined context.</param>
    public Hotel(SerializationInfo si, StreamingContext context)
    {

    }
    
    /// <summary>
    /// Le constructeur.
    /// </summary>
    public Hotel()
    { }
}

Conclusion

Le tour est joué.

Ce document intitulé « Soap Serialiser générique et Liste<T> » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous