ISerializable接口有什么意义?

leo*_*ora 51 c# serializable iserializable

看起来我可以序列化没有该接口的类,所以我不清楚它的用途.

Mar*_*ell 66

ISerializable用于提供自定义二进制序列化,通常用于BinaryFormatter(也可能用于远程处理).没有它,它使用字段,可以是:

  • 效率低下; 如果有些字段仅用于运行时的效率,但可以删除以进行序列化(例如,序列化时字典可能看起来不同)
  • 效率低下; 即使对于需要的字段,它也需要包含许多额外的元数据
  • 无效; 如果有无法序列化的字段(例如事件代理,尽管可以标记[NonSerialized])
  • 脆; 您的序列化现在绑定到字段名称 - 但字段是一个实现细节; 另请参见混淆,序列化和自动实现的属性

通过实现,ISerializable您可以提供自己的二进制序列化机制.请注意,xml等效于此IXmlSerializable,XmlSerializer等等.

对于DTO目的,BinaryFormatter应该避免 - 像xml(via XmlSerializerDataContractSerializer)或json 这样的东西都很好,像协议缓冲区这样的跨平台格式也是如此.

为了完整起见,protobuf-net确实包含了钩子ISerializable(允许你使用便携式二进制格式而无需编写大量代码),但BinaryFormatter无论如何都不会是你的首选.


Nol*_*rin 9

可以使用以下两种方法之一在.NET中对类进行序列化:

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

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

关于后者(ISerializable)及其用法,我引用了MSDN页面中的接口:

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

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


ang*_*son 5

随着ISerializable您可以编写自定义的方法,你的对象执行二进制序列化时,序列化以不同的方式比通过BinaryFormatter的使用默认的做法会做你的对象接管系列化.

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

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

感谢Marc和Pop的评论,我的第一个答案有点仓促.