Question

J'ai eu un problème avec la sérialisation de mes objets et je l'ai réduit à un cas spécifique (voir le code ci-dessous). Je recevais l'erreur suivante:

Erreur 1 Fichier Resx non valide. Impossible de charger le type Serialisation.Harness.Blob, Serialization, Version = 1.0.0.0, Culture = neutre, PublicKeyToken = null utilisé dans le fichier .RESX. Assurez-vous que les références nécessaires ont été ajoutées à votre projet. Ligne 129, position 5. ...

Ce qui est vraiment étrange, c’est que le redémarrage de Visual Studio provoque la disparition de l’erreur et le code fonctionne, mais après un nombre de constructions apparemment aléatoire (pendant lequel ledit code n’est pas modifié) il va se briser à nouveau.

Pouvez-vous voir ce que je fais mal / manque?

Merci d'avance,

Méto

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.Windows.Forms.Design; using System.ComponentModel.Design;

namespace Serialisation.Harness
{    

    [Serializable]
    public class Blob
    {
        public Blob()
        {
        }
    }

    [Serializable]
    public class Basic
    {

        private List<Blob> blobs;
        public List<Blob> Blobs
        {
            get { return blobs; }
            set { this.blobs= value; }
        }

        public Basic()
        {
            basics = new List<Blob>();
        }

    }

    public class BasicComponent : Component
    {

        private Basic basic = new Basic();

        private IContainer components = new Container();

        public List<Blob> Blobs
        {
            get { return basic.Blobs; }
            set { basic.Blobs= value; }
        }

        public BasicComponent(IContainer container)
        {
            container.Add(this);
        }

    }

}
Était-ce utile?

La solution

Tout d'abord, l'attribut Serializable est non utilisé pour la sérialisation du concepteur. Lors de la sérialisation des objets, le concepteur sera sérialisé dans le fichier de ressources s'il ne sait pas l'écrire dans le code du concepteur. Ceci est écrit dans le resx sous forme de blob à l'aide d'un InstanceDescriptor pour le constructeur par défaut du type d'objet (les valeurs de propriété que vous souhaitez également inclure sont perdues). C’est ce qui se passe pour la propriété Blobs car le concepteur ne sérialise pas correctement les listes génériques (il sait cependant comment sérialiser les tableaux).

Pour conserver les informations à l'intérieur de ces objets persistants, vous devez créer un fichier TypeConverter qui spécifie un constructeur différent dans le fichier BasicComponent (une version qui prend un certain état pour décrire les propriétés, telles que votre propriété IEnumerable<Blob>). Par exemple, si vous avez ajouté un constructeur à votre type Blob prenant un List<Blob>, vous pouvez obtenir un CodeDomSerializer à ce constructeur, en passant un tableau de <=> s (vous créez un nouveau <=> autour de celui-ci dans le constructeur ). Parce que le concepteur sait comment conserver une <=> pour coder, et comme il sait comment persister les tableaux, il les ajoutera ensuite à votre code de concepteur plutôt qu'à la resx.

Vous pouvez également implémenter un <=> pour spécifier le code utilisé pour décrire votre instance, que le concepteur peut utiliser pour enregistrer votre objet dans le code du concepteur plutôt que dans le resx.

Convertisseur de type

Pour utiliser l'approche du convertisseur de type, procédez comme suit:

public class BasicComponentTypeConverter : TypeConverter
{
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        bool canConvert = base.CanConvertTo(context, destinationType);

        if (!canConvert &&
            (destinationType == typeof(InstanceDescriptor))
        {
            canConvert = true;
        }

        return canConvert;
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
        object conversion = null;

        if (culture == null)
        {
            culture = CultureInfo.CurrentCulture;
        }

        BasicComponent component = value as BasicComponent;
        if (basicComponent != null)
        {
            if (destinationType == typeof(InstanceDescriptor))
            {
               // Note that we convert the blobs to an array as this makes for nicer persisted code output.
               // Without it, we might just get a resource blob which is not human-readable.
               conversion = new InstanceDescriptor(
                   typeof(BasicComponent).GetConstructor(new Type[] { typeof(IEnumerable<Blob>) }),
                   new object[] { basicComponent.Blobs.ToArray() },
                   true);
            }
        }

        if (conversion == null)
        {
            conversion = base.ConvertTo(context, culture, value, destinationType);
        }

        return conversion;
    }
}

Notez que vous devrez peut-être également écrire un convertisseur de type pour le type <=>. Pour associer le convertisseur de type au type, déclarez simplement le <=> attribut sur la classe que le convertisseur de type convertira, c'est-à-dire BasicConverter pour l'exemple ci-dessus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top