1
votes

Comment enregistrer / charger sur une classe de disque avec des propriétés non sérialisables?

J'ai une classe qui doit être enregistrée sur le disque, puis chargée à chaque fois que l'application est initialisée. Peu m'importe si le fichier créé est un Json, XML ou binaire. Voici la classe:

    public class Milestone_v01
    {
        public bool     freeMilestone { get; set; }
        public string   Title { get; set; }
        public double   Latitude { get; set; }
        public double   Longitude { get; set; }
        public double   Altitude { get; set; }
        public globalVars.Astro Astro { get; set; }
    }

    public enum Astro
    {
        Sun, Moon, Night, Any
    }


    public class Image_v01
    {
        public string imageURI { get; set; }
        public bool   isDownloaded { get; set; }
    }

    public class URL_v01
    {
        public string sURL { get; set; }
    }

    public class Tag_v01
    {
        public globalVars.Tags TagName { get; set; }
    }

    public class Date_v01
    {
        public DateTime DateStart { get; set; }
        public DateTime DateEnd { get; set; }
    }

Et ici, classes et énumérations, ... utilisées dans la classe principale:

    public class PhotoSpot_v01
    {
        public int      ID { get; set; }
        public string   Title { get; set; }
        public string   Description { get; set; }
        public int      Rating { get; set; }
        public bool     Reminder { get; set; }
        public bool     Toast { get; set; }

        private double   Latitude { get; set; }
        private double   Longitude { get; set; }
        private double   Altitude { get; set; }

        public GoogleMapsAPI.TimeZone TimeZone { get; set; }

        public globalVars.Tags MainTag { get; set; }

        public version Version { get; set; }

        public Milestone_v01    Milestone { get; set; }
        public List<Image_v01>  Images { get; set; }
        public List<URL_v01>    URLs { get; set; }
        public List<globalVars.Tag>    Tags { get; set; }
        public List<Date_v01>   Dates { get; set; }}

Comment puis-je réussir à enregistrer les valeurs d'énumération et spécialement les valeurs DateTime et Geopoint?


4 commentaires

Les valeurs enum sont généralement sérialisées comme leurs valeurs int .


qu'est-ce que Geopoint ici? il n'apparaît pas dans l'exemple de code - est-ce une API spécifique?


aussi: quels types considérez-vous comme "non sérialisable" dans ce qui précède? la plupart si cela semble assez raisonnable, même si nous ne pouvons pas tout voir (aucune idée de ce que sont les Tags / Tag / TimeZone , par exemple)


@MarcGravell Geopoint est une classe pour travailler avec la position géospatiale à la surface de la Terre. docs.microsoft.com/en-us/uwp/ api /… Les balises / balises sont des énumérations et TimeZone c'est une classe avec seulement des valeurs doubles et des chaînes, donc rien de problématique, c'est pourquoi je n'ai pas inséré dans le code ci-dessus.


3 Réponses :


3
votes

En fait, je ne vois rien de "non sérialisable" dans votre modèle (il semble que l'un des principaux fonctionnerait très bien avec cela - en particulier XmlSerializer , Json.NET et protobuf-net , qui sont mes valeurs par défaut habituelles); aucun sérialiseur de note ne devrait s'étouffer avec les énumérations ou DateTime . Mais: s'il y a vraiment est un type problématique quelque part, il y a deux manières de le faire:

  1. la plupart des outils / bibliothèques de sérialisation prennent en charge une sorte d'API de «sérialiseur personnalisé» lorsque quelque chose ne fonctionne tout simplement pas. cela vous oblige généralement à en apprendre trop manière sur l’architecture de sérialisation sous-jacente (exemple: IXmlSerializable.ReadXml - ce qui est juste un cauchemar pour obtenir à 100% le droit à tous les scénarios); Je ne recommande pas généralement d'essayer de le faire!
  2. beaucoup plus simple: cessez d'essayer de sérialiser des choses qui ne sont pas naturellement sérialisables . Ce problème se produit généralement lorsque les gens insistent sur le fait qu'ils veulent sérialiser leur modèle principal , mais ... cela ne fait que faire les choses dans le mauvais sens: vous finissez par combattre le sérialiseur. Il est beaucoup plus simple et maintenable de construire un modèle séparé qui ressemble similaire à votre modèle principal, mais qui est purement destiné à s'adapter aux nuances d'un sérialiseur particulier (si vous prenez en charge plusieurs formats de sérialisation ou différentes versions de sérialisation , vous pourriez même avoir besoin de plusieurs modèles dans certains cas). Donc: créez quelque chose comme votre modèle, mais qui n'utilise que des types intrinsèquement sérialisables - puis écrivez quelques lignes de code (généralement très simple) qui mappe entre les deux modèles.

Dans certains cas de 2, l'outil de sérialisation peut même prendre en charge un concept de «substitut» tel que vous n'avez besoin d'ajouter ce modèle que pour certains types, lorsqu'ils deviennent gênants - mais peut utiliser le modèle pour la plupart des autres choses. Par exemple, protobuf-net vous permet de le faire tant qu'il y a une opération de conversion (implicite ou explicite) dans les deux sens entre deux types - vous pouvez donc avoir un type Foo , et un Type FooSerialization qui ressemble beaucoup à Foo , et a des opérateurs de conversion vers / depuis Foo , mais qui est "plus simple" (faute d'un meilleur mot ) - en utilisant des types simples évidents (par exemple, peut-être en utilisant byte [] au lieu de Image / Bitmap pour les images).


6 commentaires

Merci d'avoir répondu. J'essayais la deuxième approche pour obtenir ce que je voulais: convertir Geopoint en quelque chose de sérialisable (double longitude, double latitude, double altitude) et ajouter une méthode pour obtenir de la classe convertie en classe Geopoint. Donc, de cette façon, je peux rejeter Geopoint pour être quelque chose de problématique, tout comme moi avec les énumérations. Cela me permet avec la structure DateTime.


@ImanolZubiaurre dans ce scénario, Geopoint ressemble à quelque chose pour lequel l'API "substitut" de protobuf-net fonctionnerait bien; Je vais vous donner un exemple plus complet ...


@ImanolZubiaurre note ... vous n'utilisez pas réellement Geopoint dans votre code ... alors ...


@ImanolZubiaurre un peu comme ça: gist.github.com/mgravell/6b2ca16de970051d28584ef6cc


Si j'ai bien compris, DateTime est sérialisable sans autre problème. Si cela est correct et que j'ai géré la conversion Geopoint en 3 valeurs doubles similaires (latitude, longitude et altitude) qui peuvent être sérialisables. Mon problème devrait être résolu.


@ImanolZubiaurre à peu près tous les sérialiseurs que je connais peuvent gérer DateTime ; Geopoint pourrait être le plus délicat, donc mon exemple montre une façon d'utiliser une fonctionnalité spécifique à la bibliothèque (types de substitution) pour caler dessus sans avoir besoin de créer un modèle séparé entier . Divulgation: Je suis l'auteur / mainteneur de protobuf-net, donc je suis bien meilleur pour donner des exemples de cette bibliothèque qu'avec les autres - des fonctionnalités similaires peuvent être disponibles sur json.net, etc.



0
votes

Je suggère d'utiliser newtonsoft.json.

Vous pouvez écrire un convertisseur json pour les valeurs DateTime et GeoPoint pour les conserver sous la forme souhaitée, puis les traduire lorsque vous désérialisez.


0 commentaires

0
votes

Répondant à Marc Gravell dans la conversation ci-dessus que je ne peux pas publier de code formaté ...

Donc, si je modifie DateTime dans la classe Date_v01, cela peut être vu dans le code donné dans la question (et dans extension à Geopoint aussi):

    public class Date_v01
    {

        public double DateStart;
        public double DateEnd;

        public DateTime DateTimeStart()
        {
            return CoreTime.JD2DateTime(DateStart);
        }

        public DateTime DateTimeEnd()
        {
            return CoreTime.JD2DateTime(DateEnd);
        }

        //public DateTime DateStart { get; set; }
        //public DateTime DateEnd { get; set; }
    }

le problème de sérialisation devrait être résolu, non?


0 commentaires