C# ISerializable 接口的意义是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/810974/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 02:06:54  来源:igfitidea点击:

What is the point of the ISerializable interface?

c#serializableiserializable

提问by leora

It seems like I can serialize classes that don't have that interface, so I am unclear on its purpose.

似乎我可以序列化没有该接口的类,所以我不清楚它的目的。

采纳答案by Marc Gravell

ISerializableis used to provide custom binary serialization, usually for BinaryFormatter(and perhaps for remoting purposes). Without it, it uses the fields, which can be:

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

  • inefficient; if there are fields that are only used for efficiency at runtime, but can be removed for serialization (for example, a dictionary may look different when serialized)
  • inefficient; as even for fields that are needed it needs to include a lot of additional metadata
  • invalid; if there are fields that cannotbe serialized (such as event delegates, although they can be marked [NonSerialized])
  • brittle; your serialization is now bound to the fieldnames - but fields are meant to be an implementation detail; see also Obfuscation, serialization and automatically implemented properties
  • 效率低下;如果有一些字段只在运行时用于提高效率,但可以删除以进行序列化(例如,序列化时字典可能看起来不同)
  • 效率低下;即使对于需要的字段,它也需要包含大量额外的元数据
  • 无效的; 如果有不能序列化的字段(比如事件委托,虽然可以标记[NonSerialized]
  • 脆; 您的序列化现在绑定到字段名称 - 但字段是一个实现细节;另见混淆、序列化和自动实现的属性

By implementing ISerializableyou can provide your own binary serialization mechanism. Note that the xml equivalent of this is IXmlSerializable, as used by XmlSerializeretc.

通过实现,ISerializable您可以提供自己的二进制序列化机制。请注意,与此等价的 xml 是IXmlSerializable,如XmlSerializer等所使用。

For DTO purposes, BinaryFormattershould be avoided - things like xml (via XmlSerializeror DataContractSerializer) or json are good, as are cross-platform formats like protocol buffers.

出于 DTO 目的,BinaryFormatter应该避免 - 像 xml (viaXmlSerializerDataContractSerializer) 或 json 之类的东西很好,就像协议缓冲区这样的跨平台格式一样。

For completeness, protobuf-net does include hooks for ISerializable(allowing you to use a portable binary format without writing lots of code), but BinaryFormatterwouldn't be your first choice here anyway.

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

回答by Lasse V. Karlsen

With the ISerializableyou can write custom methods in your object to take over serialization when doing binary serialization, to serialize your objects in a different manner than what the default approach used by BinaryFormatter will do.

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

In other words, if the default approach serializes your object in a different manner than how you want it to serialize as, you can implement ISerializable for complete control. Note that hand in hand with ISerializable, there's also a custom constructor you should implement.

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

XmlSerialization will of course only use properties, ISerializable has nothing to do with XML serialization.

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

Thanks Marc and Pop for the comments, I was a bit hasty with my first answer.

感谢 Marc 和 Pop 的评论,我的第一个回答有点草率。

回答by Noldorin

Classes can be serialized in .NET in one of two ways:

可以通过以下两种方式之一在 .NET 中序列化类:

  1. Marking the class with SerializableAttributeand decorating all the fields that you don'twant to be serialized with the NonSerializedattribute. (As Marc Gravell points out, BinaryFormatter, which is the class typically used to format ISerializableobjects, automatically serializes all fields unless they are specifically marked otherwise.)
  2. Implementing the ISerializableinterface for fully custom serialization.
  1. 标记与类SerializableAttribute和装饰你的所有字段希望与序列化NonSerialized属性。(正如 Marc Gravell 所指出的,BinaryFormatter,这是通常用于格式化ISerializable对象的类,自动序列化所有字段,除非它们被特别标记。)
  2. 实现ISerializable完全自定义序列化的接口。

The former is simpler to use as it simply involves marking declarations with attributes, but is limited in its power. The latter allows more flexibility but takes significantly more effort to implement. Which one you should use depends completely on the context.

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

Regarding the latter (ISerializable) and it usage, I've quoted from the MSDN pagefor the interface:

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

Any class that might be serialized must be marked with the SerializableAttribute. If a class needs to control its serialization process, it can implement the ISerializable interface. The Formatter calls the GetObjectData at serialization time and populates the supplied SerializationInfo with all the data required to represent the object. The Formatter creates a SerializationInfo with the type of the object in the graph. Objects that need to send proxies for themselves can use the FullTypeName and AssemblyName methods on SerializationInfo to change the transmitted information.

In the case of class inheritance, it is possible to serialize a class that derives from a base class that implements ISerializable. In this case, the derived class should call the base class implementation of GetObjectData inside its implementation of GetObjectData. Otherwise, the data from the base class will not be serialized.

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

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

回答by splattne

In order to make an object "transportable", you have to serialize it. For example, if you want to transfer object data using .NET Remoting or Web Services you have to provide methods which serializes your object data, reducing your object instances into a transportable format that represents a high-fidelity representation of the object.

为了使对象“可传输”,您必须对其进行序列化。例如,如果您想使用 .NET Remoting 或 Web 服务传输对象数据,您必须提供序列化您的对象数据的方法,将您的对象实例减少为表示对象的高保真表示的可传输格式。

You then may also take the serialized representation, transport it to another context such as a different machine, and rebuild your original object.

然后,您还可以获取序列化的表示,将其传输到另一个上下文(例如不同的机器),并重建您的原始对象。

When implementing the ISerializableinterface, a class must provide the GetObjectData method that is included in the interface, as well as a specialized constructor that is specialized to accept two parameters: an instance of SerializationInfo, and an instance of StreamingContext.

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

If your classes don't require fine-grained control of their object state, then you could just use [Serializable]attribute. Classes that require more control over the serialization process can implement the ISerializable interface.

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