ISerializable 接口的意义何在?
Posted
技术标签:
【中文标题】ISerializable 接口的意义何在?【英文标题】:What is the point of the ISerializable interface? 【发布时间】:2010-10-23 02:19:35 【问题描述】:似乎我可以序列化没有该接口的类,所以我不清楚它的目的。
【问题讨论】:
ISerializable 是一个接口,而不是一个属性。您的问题是关于接口 ISerializable 还是 SerializableAttribute 类? @Martin,在问题本身中,他只提到了属性。所以我想问题不在于界面。如果有人可以编辑问题标题? 我和 Martin 一样对这个问题感到困惑,但我认为这是关于界面的,因为他特别提到了 ISerializable。 @mek:如果您实际上是指属性,请让我知道/编辑问题。 对问题的错误编辑,它是关于属性......而不是界面。他用了两次属性这个词 【参考方案1】:ISerializable
用于提供自定义二进制序列化,通常用于BinaryFormatter
(也可能用于远程处理)。没有它,它使用的字段可以是:
[NonSerialized]
)
易碎;您的序列化现在绑定到 field 名称 - 但字段意味着实现细节;另见Obfuscation, serialization and automatically implemented properties
通过实现ISerializable
,您可以提供自己的二进制序列化机制。请注意,与 IXmlSerializable
等效的 xml 是 XmlSerializer
等所使用的。
出于 DTO 目的,应避免使用 BinaryFormatter
- xml(通过 XmlSerializer
或 DataContractSerializer
)或 json 之类的东西很好,协议缓冲区之类的跨平台格式也是如此。
为了完整起见,protobuf-net 确实包含ISerializable
的挂钩(允许您使用可移植的二进制格式而无需编写大量代码),但BinaryFormatter
无论如何都不是您的首选。
【讨论】:
很好的答案!只是标记,如果序列化类型标有“System.Serializable”属性,DataContractSerializer 也可以使用 ISerializable 进行自定义 XML 序列化(参见 answer 中的 TestClass2)【参考方案2】:可以通过以下两种方式之一在 .NET 中对类进行序列化:
-
用
SerializableAttribute
标记类,并用NonSerialized
属性装饰您不想要序列化的所有字段。 (正如 Marc Gravell 所指出的,BinaryFormatter
是通常用于格式化 ISerializable
对象的类,它会自动序列化所有字段,除非它们另有特别标记。)
实现ISerializable
接口以实现完全自定义的序列化。
前者使用起来更简单,因为它只涉及用属性标记声明,但它的功能有限。后者允许更大的灵活性,但需要付出更多的努力来实施。您应该使用哪一个完全取决于上下文。
关于后者 (ISerializable
) 及其用法,我已经引用了MSDN page 的接口:
任何可能被序列化的类 必须标有 可序列化属性。如果一个班级 需要控制它的序列化 过程中,它可以实现 ISerializable 接口。格式化程序 调用 GetObjectData 在 序列化时间并填充 提供了所有的 SerializationInfo 表示所需的数据 目的。格式化程序创建一个 SerializationInfo 的类型为 图中的对象。需要的对象 为自己发送代理可以使用 FullTypeName 和 AssemblyName SerializationInfo 上要更改的方法 传输的信息。
在类继承的情况下,它 可以序列化一个类 派生自一个基类 实现 ISerializable。在这个 情况下,派生类应该调用 的基类实现 GetObjectData 里面 GetObjectData 的实现。 否则,来自基础的数据 类不会被序列化。
【讨论】:
Re point 1:BinaryFormatter(ISerializable的主要消费者)不关心属性,默认使用所有字段(需要选择退出) (我修复了 NonSerialized 属性名称;希望你不要介意。我在原来的帖子中也弄错了...... ;-p) 当然,序列化类的第三种方式是使用XML Serializer,第四种方式是使用Data Contract Serializer。 @Marc:当然不是。 :) 正如你所看到的,我对关于序列化的属性名称有点模糊。无论如何,你的答案更完整,所以嗯。【参考方案3】:使用ISerializable
,您可以在对象中编写自定义方法,以便在进行二进制序列化时接管序列化,以不同于 BinaryFormatter 使用的默认方法的方式序列化对象。
换句话说,如果默认方法以不同于您希望它序列化的方式序列化您的对象,您可以实现 ISerializable 以获得完全控制。请注意,与 ISerializable 一起,您还应该实现一个自定义构造函数。
XmlSerialization 当然只会使用属性,ISerializable 与 XML 序列化无关。
感谢 Marc 和 Pop 的 cmets,我的第一个答案有点草率。
【讨论】:
这个答案不正确; ISerializable 与 BinaryFormatter 相关; “public with get/set”与 XmlSerializer 有关——两者是非常不同的野兽,具有完全不同的规则。 这仅适用于 XML 序列化,二进制序列化序列化对象(私有或公共)的字段,而不是通过属性读取的对象的外部图像。这是 ISerializable 最有用的地方。【参考方案4】:为了使对象“可传输”,您必须对其进行序列化。例如,如果您想使用 .NET Remoting 或 Web 服务传输对象数据,则必须提供序列化对象数据的方法,将对象实例减少为表示对象高保真表示的可传输格式。
然后,您还可以获取序列化表示,将其传输到另一个上下文(例如不同的机器),然后重建您的原始对象。
当实现ISerializable
接口时,一个类必须提供接口中包含的GetObjectData 方法,以及一个专门接受两个参数的专用构造函数:一个SerializationInfo 实例和一个StreamingContext 实例。
如果您的类不需要对其对象状态进行细粒度控制,那么您可以只使用[Serializable]
属性。需要对序列化过程进行更多控制的类可以实现 ISerializable 接口。
【讨论】:
有中途点吗?我很想对某些领域进行一些类似于 ISerializable 的控制,但对于其他领域,我会退回到通常的机制。 是与否,到了一半。您可以在要序列化的所有字段/属性上尝试“DataContractAttribute”和“DataMemberAttribute”,在所有不想序列化的字段/属性上尝试“IgnoreDataMemberAttribute”。还有一些属性可用于预处理和后处理(反)序列化的方法,例如“OnSerializingAttribute”和“OnDeserializedAttribute”。我用它执行了一些黑魔法:序列化一个对象结构,该结构使用动态加载的 dll 中的类,并序列化这些 dll,以便将它们重新加载以再次加载所有内容。为此,我去了 .dll 地狱。以上是关于ISerializable 接口的意义何在?的主要内容,如果未能解决你的问题,请参考以下文章