• 第二节:使类型可序列化


    设计一个类型时,设计人员必须郑重地决定是否允许类型的实例序列化。类型默认是不可序列化的。例如,以下代码可能不会像你希望的那样工作:

    internal struct Point { public Int32 x, y;}
    private static void OptInSerialization()
            {
                Point pt = new Point { x = 1, y = 2 };
                using (var stream = new MemoryStream())
                {
    
                    new BinaryFormatter().Serialize(stream, pt);//抛出 SerializationException
                }
            }

    如果在你的程序中生成并运行上述代码,会发现格式化器的Serialize方法抛出一个异常。问题在于,Point类型的开发人员没有显示的指出Point对象可以序列化。为了解决这个问题,开发人员必须像下面这样向这个类型应用一个名为System.SerializableAttribute的定制的attribute。(注意,这个attribute是在System命名空间中定义的,而不是在System.Runtime.Serialization命名空间中定义的。)

    [Serializable]
    internal struct Point { public Int32 x, y;}

    现在,如果重新生成运行应用程序并运行它,就会像预期那样工作,Point对象会顺利序列化到流中。序列化一个对象图时,格式化器会检查每个对象的类型都是可序列化的。如果对象图中的任何一个对象不可序列化,格式化器的Serialize方法都会抛出一个SerializationException异常。

    注意:序列化一个对象图时,有的对象的类型也许能序列化,有的也许不能。考虑到性能,在序列化之前,格式化器不会验证对象图中的所有对象都能序列化。所以,序列化一个对象图时,在抛出SerializationException之前,完全有可能已经有一部分对象已经序列化到流中。如果发生这种情况,流中就会包含以损坏的数据。序列化一个对象时。如果你认为也许有一些对象不可序列化,那么写代码就应该能得体的从这些异常中恢复。一个方案是先将对象序列化到MemoryStream中。然后,如果所有对象都成功序列化,就可以将MemoryStream中的字节复制到你真正希望的目标流中(比如文件和网络)。

    SerializableAttribute这个定制的attribute只能应用于引用类型(class)、值类型(struct)、枚举类型(enum)和委托(delegate)。注意,枚举和委托类型总是可序列化的,所以不必显示应用SerializableAttribute。除此之外,SerializableAttribute不会被派生继承。所以,给定以下两个类型定义,那么Person对象时可序列化的,而Employee对象时不可序列化的:

      [Serializable]
      class Person { } internal class Employee : Person { }

    为了解决这个问题,只要将SerializableAttribute应用于Employee类型:

    [Serializable]
        internal class Person { }
        [Serializable]
        internal class Employee : Person
        { 
        }

    注意,上诉问题虽然很容易修正,但反之则不然。如果一个类型没有应用SerializableAttribute,那么很难想象如何从它派生出一个可序列化的类型。但这样设计时有原因的:如果基类不允许他的实例序列化,它的字段就不能序列化,因为基对象实际是派生对象的一部分。这正是为什么System.Object已经很体贴的应用了SerializableAttribute的原因。

    注意:通常,建议你定义的大多数类型都设置成可序列化,毕竟,这能为类型的用户提供很大的灵活性。但是必须注意,序列化会读取一个对象的所有字段,不管这些字段声明为public,protected,internal还是private。如果一个类型的实例要包敏感和安全数据,或者数据在转移之后使没有含义或者没有值,就不应该使类型变的可序列化。

    如果使用的一个类型不是为序列化而设计的,而且手上没有类型的源代码,无法从源代码添加序列化支持。在后面“反序列化对象时重写程序集和/类型”中,我会解释如何使任何不可序列化的类型变的可序列化。

  • 相关阅读:
    APP性能测试中的几个重要概念
    linux初学体会
    Centos 关闭指定端口的进程
    【初学Python】01-第一个小说爬虫
    SQLsever存储过程分页查询
    记MVC学习过程中一次传参到View时遇到的错误
    未能加载文件或程序集“System.Web.Mvc, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项
    Android Studio导包无效,全部报红
    记一次使用SimpleDateFormat 格式化时间时遇到的问题
    Spring-Boot中Tomcat端口修改
  • 原文地址:https://www.cnblogs.com/bingbinggui/p/4621167.html
Copyright © 2020-2023  润新知