【问题标题】:How to save/load to disk class with non serializable properties?如何保存/加载到具有不可序列化属性的磁盘类?
【发布时间】:2019-06-03 01:51:17
【问题描述】:

我有一个类必须保存到磁盘,然后在每次应用初始化时加载。我不在乎创建的文件是 Json、XML 还是二进制文件。这是课程:

    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; }}

在这里,类和枚举,......在主类中使用:

    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; }
    }

如何保存枚举值,特别是 DateTime 和 Geopoint 值?

【问题讨论】:

  • enum 值通常被序列化为它们的int 值。
  • 这里的Geopoint 是什么?它没有出现在代码示例中 - 这是一个特定的 API 吗?
  • 另外:您在上面考虑哪些类型是“不可序列化”的?大多数情况下看起来很合理,尽管我们无法看到所有内容(例如,不知道 Tags/Tag/TimeZone 是什么)
  • @MarcGravell Geopoint 它是一个处理地球表面地理空间位置的类。 docs.microsoft.com/en-us/uwp/api/…Tags/Tag 是枚举,TimeZone 是只有 double 和 string 值的类,所以没有问题,这就是为什么我没有在上面的代码中插入。

标签: c# class uwp save serializable


【解决方案1】:

我实际上并没有在您的模型中看到任何“不可序列化”的东西(看起来任何主要的都可以很好地处理它 - 特别是 XmlSerializer、Json.NET 和 protobuf-net,这是我常用的默认值);没有值得注意的序列化程序会阻塞枚举或DateTime。但是:如果某处确实有有问题的类型,有两种方法可以做到这一点:

  1. 大多数序列化工具/库都支持某种“自定义序列化程序”API,以便在某些东西无法开箱即用时使用;这通常需要您方式过多地了解底层序列化架构(例如:IXmlSerializable.ReadXml - 这对于所有场景都 100% 正确来说是一场噩梦);我通常建议尝试这样做!
  2. 更简单:停止尝试序列化不能自然序列化的东西。当人们坚持他们想要序列化他们的主模型时,通常会出现这个问题,但是......这只是错误的方式:你最终与序列化程序作斗争。更简单且更易于维护的是构建一个与您的主要模型相似的单独模型,但这纯粹是为了适应特定序列化程序的细微差别(如果您支持多种序列化格式或不同的序列化版本,在某些情况下您甚至可能需要多个模型)。所以:创建类似你的模型的东西,但它只使用固有的可序列化类型 - 然后编写几行(通常非常简单的)代码来映射两者之间的模型。

在 2 的某些情况下,序列化工具甚至可能支持“代理”概念,这样您只需为 一些 类型添加此模型,当它们变得笨拙时 - 但可以使用主要大多数其他事物的模型。例如,protobuf-net 允许您执行此操作,只要在两种类型之间的双向转换操作(隐式或显式) - 所以您可以有一个 Foo 类型和一个 FooSerialization 类型,看起来很像Foo,并且有与Foo 之间的转换运算符,但它“更简单”(因为需要一个更好的词)——利用明显的简单类型(例如,可能使用byte[] 而不是@ 987654330@/Bitmap 图片)。

【讨论】:

  • 谢谢您的回答。我正在尝试第二种方法来获得我想要的东西:Geopoint 转换为可序列化的东西(双经度、双纬度、双高度)并添加一个方法以从转换回 Geopoint 类的类中获取。因此,通过这种方式,我可以将 Geopoint 丢弃为有问题的东西,枚举也是如此。这让我可以使用 DateTime 结构。
  • @ImanolZubiaurre 在那种情况下,Geopoint 听起来像是 protobuf-net 的“代理”API 可以很好地工作的东西;我会整理一个更完整的例子......
  • @ImanolZubiaurre 注意...您实际上并没有在代码中使用 Geopoint...所以...
  • 如果我理解正确的话,DateTime 是可序列化的,没有任何进一步的问题。如果这是正确的并且他们管理 Geopoint 转换为可序列化的类似 3 个双精度值(纬度、经度和高度)。我的问题应该解决了。
【解决方案2】:

我建议使用 newtonsoft.json。

您可以为 DateTime 和 GeoPoint 值编写 json 转换器,以使它们保持您想要的形式,然后在反序列化时将它们转换回来。

【讨论】:

    【解决方案3】:

    在上面的对话中回复 Marc Gravell 我无法发布格式化代码...

    因此,如果我在 Date_v01 类中对 DateTime 进行此更改,则可以在问题给出的代码中看到它(以及对 Geopoint 的扩展):

        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; }
        }
    

    序列化问题应该解决了吧?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-26
      相关资源
      最近更新 更多