为什么一个对象需要Serializable属性才能被序列化

40

据我的理解,SerializableAttribute 提供的检查是在运行时而非编译时进行的。如果是这样,那么为什么需要将类标记为可序列化呢?

序列化器难道不能尝试对对象进行序列化并在失败时停止吗?现在它不就是这样做的吗?如果必须将可序列化事项标记为不可序列化,那么这样不会更好吗?这样一来,你就不必担心库没有将事项标记为可序列化了。


可能是重复的问题:为什么必须使用属性 [Serializable] 标记一个类?(原文链接:https://dev59.com/6XE85IYBdhLWcg3w03Dz) - nawfal
你可以尝试使用PostSharp自动为所有类添加属性。类似的用法在这个问题中有展示:https://dev59.com/XVzUa4cB1Zd3GeqP3XV- - Markus Weber
2个回答

46

据我理解,SerializableAttribute 的想法是创建一个二进制序列化的选择加入系统。

需要注意的是,与使用公共属性的 XML 序列化不同,二进制序列化默认情况下获取所有私有字段。

这不仅可能包括操作系统结构和不应该暴露的私有数据,而且对其进行反序列化可能会导致崩溃应用程序的损坏状态(荒唐的例子:句柄指向在另一台计算机上打开的文件)。


2
+1 - 基本上,安全性和非公开信息的泄露是这里面的问题。 - TomTom
1
只有回答解释了为什么二进制序列化是必需的。做得好,所有答案中都缺少这个。 - Remy van Duijkeren

23
这仅适用于BinaryFormatter (以及SOAP的等效方式,但没有人使用它)。迪亚哥是正确的; 就其所做的事情而言,有很好的理由,但它离是唯一的选择还有很大的差距 - 实际上,我个人仅推荐在AppDomains之间通信时使用BinaryFormatter - 它不是(依我之见)将数据持久化(到磁盘、缓存、数据库BLOB等)的好方法。

如果这种行为给你带来了麻烦,请考虑使用以下任何一种替代方案:

  • XmlSerializer,它可以处理公共成员(不仅仅是字段),但需要一个公共无参构造函数和公共类型
  • DataContractSerializer,它可以完全自定义(使用[DataContract]/[DataMember]),但也可以(在3.5及以上版本中)根据字段进行工作

另外 - 对于第三方选项(我是第三方); protobuf-net 可能在这里有选项; "v2"(尚未完全发布,但可作为源代码提供)允许独立描述模型(序列化哪些成员等),因此可以应用于您不控制的类型。而且,与BinaryFormatter不同,输出是版本容忍的、已知的公共格式等。


太棒了。这篇文章精彩地总结了在C#中进行序列化的选择,以及它们的优缺点。正是我上周一直在寻找的内容...谢谢Marc。 - Arthis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接