什么是ISerializable接口?

看来我可以序列化没有这个接口的类,所以我不清楚它的用途。

ISerializable用于提供自定义二进制序列化,通常用于BinaryFormatter (也许用于远程处理目的)。 没有它,它使用的领域,可以是:

  • 效率低下; 如果有些字段只在运行时用于提高效率,但可以将其移除以进行序列化(例如,字典在序列化时可能会有所不同)
  • 效率低下; 因为即使是需要的字段,也需要包含大量额外的元数据
  • 无效; 如果有字段不能被序列化(比如事件委托,尽pipe它们可以被标记为[NonSerialized]
  • 脆; 您的序列化现在绑定到字段名称 – 但字段是为了实现的细节; 另请参阅混淆,序列化和自动实现的属性

通过实现ISerializable你可以提供你自己的二进制序列化机制。 请注意,这个XML的等价物是IXmlSerializable ,就像XmlSerializer所使用的一样。

对于DTO的目的, BinaryFormatter应该避免 – 像xml(通过XmlSerializerDataContractSerializer )或JSON的东西是好的,跨平台的格式,如协议缓冲区。

为了完整性,protobuf-net确实包含了ISerializable钩子(允许你使用一个可移植的二进制格式而无需编写大量的代码),但BinaryFormatter不会是你的第一select。

.NET可以通过以下两种方式之一进行序列化:

  1. 使用SerializableAttribute标记类,并装饰不想用NonSerialized属性序列化的所有字段。 (正如Marc Gravell所指出的那样, BinaryFormatter (通常用于格式化ISerializable对象的类)会自动将所有字段序列化,除非它们被另外特别标记。
  2. 实现完全自定义序列化的ISerializable接口。

前者使用起来比较简单,因为它只涉及用属性标记声明,但其function有限。 后者允许更多的灵活性,但需要更多的努力来实施。 你应该使用哪一个完全取决于上下文。

关于后者( ISerializable )及其用法,我已经从MSDN页面引用了界面:

任何可能被序列化的类都必须用SerializableAttribute标记。 如果一个类需要控制序列化过程,可以实现ISerializable接口。 格式化程序在序列化时调用GetObjectData,并用提供的所有表示对象的数据填充提供的SerializationInfo。 格式器使用图中对象的types创build一个SerializationInfo。 需要为自己发送代理的对象可以使用SerializationInfo上的FullTypeName和AssemblyName方法来更改传输的信息。

在类inheritance的情况下,可以序列化从实现ISerializable的基类派生的类。 在这种情况下,派生类应该在GetObjectData的实现中调用GetObjectData的基类实现。 否则,基类中的数据将不会被序列化。

使用ISerializable您可以在对象中编写自定义方法以在执行二进制序列化时接pipe序列化,以与BinaryFormatter使用的默认方法不同的方式序列化对象。

换句话说,如果默认方法以不同于你希望序列化的方式序列化你的对象,你可以实现ISerializable来完成控制。 请注意,与ISerializable一起,还有一个您应该实现的自定义构造函数。

XmlSerialization当然只会使用属性,ISerializable与XML序列化无关。

感谢马克和stream行音乐的评论,我的第一个答案有点草率。

为了使对象“可移动”,你必须序列化它。 例如,如果要使用.NET Remoting或Web Services传输对象数据,则必须提供序列化对象数据的方法,将对象实例减less为表示对象的高保真表示forms的可传输格式。

然后,您也可以采取序列化的表示,运输到另一个上下文,如不同的机器,并重build您的原始对象。

当实现ISerializable接口时,类必须提供接口中包含的GetObjectData方法,以及专门用于接受两个参数的专用构造函数:一个SerializationInfo实例和一个StreamingContext实例。

如果你的类不需要对它们的对象状态进行细粒度的控制,那么你可以使用[Serializable]属性。 需要更多控制序列化过程的类可以实现ISerializable接口。