【C# 序列化】可序列化类型 serializable

可序列化类型定义-serializable

类型前面添加了[serializable]特性的类就是可序列化类型,SerializableAttribute特性只能应用于引用类型(class)、值类型(struct)、枚举类型(enum)和委托类型(delegate)。枚举和委托类型总是可序列化的所以不必显示使用SerializableAttribute特性。所有不用添加[serializable]特性。

序列化必须使用到序列化器。

设计类型时,设计人员必须郑重地决定是否允许类型的实例序列化。类型默认是不可序列化的。开发者必须向类型应用定制特性system.serializableAttribute。任何对象不可序列化,格式化器的serialize方法都会抛出异常。

注意:考虑到性能,在序列化之前,格式化器不会验证对象图中的所有对象都能序列化。所以在抛出异常之前,完全有可能已经有一部分对象序列化到流中。如果发生这种情况,流中就会包含已损坏的数据。

 

soap序列化器:可以对单个对象进行序列化。但是,很大的缺陷在于,不能直接对泛型集合数据(如List<T>、ObservableCollection<T>)进行序列化(注:无论是根对象就是泛型集合,还是某个对象下的字段或属性是泛型集合,都不能序列化),
而要使用BinaryFormatter或XmlSerializer进行序列化。由于无法对泛型集合对象进行序列化,因此使用面比较窄,个人不建议使用SoapFormatter
XML序列化器:可以对单个对象或集合对象(如List<T>、ObservableCollection<T>)进行序列化。需要指出的是,需要对被序列化的对象添加[Serializable]特性
Json序列化:目前业界,普通都采用此方式,优点很多

 BinaryFormatter 以及过时。由于 类型会带来风险,不建议将其用于数据处理。 即使应用程序认为自己正在处理的数据是可信的,也应尽快停止使用 BinaryFormatterBinaryFormatter 不安全,无法确保安全。

继承性

[serializeable] 不会遗传到子类,如果子类标记为[serializeable],那么基类也必须标记[serializeable]。因为子类保护了父类。

公开性

 序列化会读取对象的所有字段保存成二进制,不管这些字段声明为public,protercted,private、internal还是readonly。 因此敏感的数据例如账号密码等字段应该设置成不可序列化[Noserializeable]。

序列化控制

可以使用:[Noserializeable]、[Noserializeable]、[OptionalField]、[OnDeserializing]、[OnSerialized]、[OnSerializing]特性对序列化进行部分控制。
[Noserializeable]: 定义不进行序列化的部分。
1、敏感的数据例如账号密码等字段应该设置成不可序列化[Noserializeable]。
2、内核对象(线程 、进程、线程、互斥体、事件、信号量)的句柄,那么在反序列化到另一个进程或者另一台机器之后,就会失去意义。因为windows 内核对象跟进程相关。
3、字段含有很容易计算的信息。主要为了减少数据传。

[Serializable]
public class DIYClass
{
    public DIYClass()
    {
        x = 10;
        y = 100;
        z = 1000;
    }

    public int x { get; set; }
    public int y { get; set; }

    [NonSerialized]
    public int z;
}

在序列化之前,该自定义对象 z 字段的值为 1000,在序列化时,检测到了忽略特性,则不会写入该字段的值到流当中。并且在反序列化之后,z 的值为 0,而 x ,y 的值是 10 和 100。

 

如有可能,应使可能包含安全敏感数据的对象不可序列化。 如果必须序列化该对象,则可将 NonSerialized 属性应用于存储敏感数据的特定字段。 如果没有将这些字段排除在序列化之外,应该注意字段存储的数据会向有权序列化的所有代码公开。 有关编写安全的序列化代码的详细信息,请参阅安全和序列化

[OptionalFiled]:类型新增字段时,新增的每个字段应该添加该属性,当格式化器看到该特性应用于一个字段时,就不会因为流中的数据不包含这个字段而抛出SerializtionException.

[OnDeserialized]:在反序列化后期运行,序列化后给字段赋值。
[OnDeserializing]:在反序列化时运行,反序列化时候修改字段值。
[OnSerialized]:在序列化完成后运行,详单与在初始化时候赋值。
[OnSerializing]:在序列化时运行,相当于初始化之后赋值。


序列化执行顺序:1、序列化一组对象时,格式化器首先调用对象的标记了OnSerializing特性的所有方法。
                         2、接着,它序列化对象的所有字段。
                         3、最后调用对象的标记了OnSerialized特性的所有方法。

反序列化执行顺序:1、反序列化一组对象时,格式化器会将这个对象的引用添加到一个内部列表中
                             2、反序列化一组对象时,格式化器首先调用对象的标记了OnDeSerializing特性的所有方法。
                             3、接着,它序反列化对象的所有字段。
                             4、最后调用对象的标记了OnDeSerialized特性的所有方法。
                            5、反向调用 格式化器内部的列表,调用每个对象的OnDeSerialized方法,这个方法被调用后,之所以要方向调用,因为这样才能使内存的对象优于外层对象。

posted @ 2022-03-05 11:56  小林野夫  阅读(4396)  评论(0编辑  收藏  举报
原文链接:https://www.cnblogs.com/cdaniu/