What is the point of the ISerializable interface?
Asked Answered
V

4

60

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

Voracious answered 1/5, 2009 at 10:56 Comment(4)
ISerializable is an interface, not an attribute. Is your question about the interface ISerializable, or the SerializableAttribute class?Cone
@Martin, in the question itself he mentions only the attribute. So I guess the question is not about the interface. If someone could edit the question title?Despairing
I was as confused as Martin about the question, but I assumed it was about the interface because he specifically mentions ISerializable. @mek: Please just let me know/edit the question if you in fact mean the attribute.Fetor
Bad edit of the question, it was about the Attribute ... not the interface. He used the word attribute twiceShaman
L
77

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

  • 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 cannot be serialized (such as event delegates, although they can be marked [NonSerialized])
  • brittle; your serialization is now bound to the field names - but fields are meant to be an implementation detail; see also Obfuscation, serialization and automatically implemented properties

By implementing ISerializable you can provide your own binary serialization mechanism. Note that the xml equivalent of this is IXmlSerializable, as used by XmlSerializer etc.

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

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

Leadin answered 1/5, 2009 at 11:6 Comment(1)
Great answer! Just flagging, ISerializable can also be used by DataContractSerializer for custom XML serialization if the serialized type is marked with the "System.Serializable" attribute (see TestClass2 in this answer )Pavid
F
10

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

  1. Marking the class with SerializableAttribute and decorating all the fields that you don't want to be serialized with the NonSerialized attribute. (As Marc Gravell points out, BinaryFormatter, which is the class typically used to format ISerializable objects, automatically serializes all fields unless they are specifically marked otherwise.)
  2. Implementing the ISerializable interface for fully custom serialization.

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 page for the interface:

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.

Fetor answered 1/5, 2009 at 11:4 Comment(4)
Re point 1: BinaryFormatter (the main consumer of ISerializable) doesn't care about properties, and uses all fields by default (you need to opt out)Leadin
(I fixed the NonSerialized attribute name; hope you don't mind. I got it wrong in my original post, too... ;-p)Leadin
Of course, the third way to serialize classes is with the XML Serializer, and the fourth way is with the Data Contract Serializer.Barner
@Marc: Of course not. :) As you can see, I'm a bit hazy on the attribute names regarding serialization. Your answer is more complete anyway, so meh.Fetor
I
5

With the ISerializable you 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.

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.

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

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

Impartial answered 1/5, 2009 at 11:2 Comment(2)
This answer is incorrect; ISerializable relates to BinaryFormatter; the "public with get/set" relates to XmlSerializer - the two are very different beasts, with completely different rules.Leadin
this is true only for XML serialization, binary serialization serializes the fields of an object (private or public) not the outside image of the object read through properties. This is where ISerializable is most useful.Omasum
O
3

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.

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 ISerializable interface, 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.

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.

Operable answered 1/5, 2009 at 11:4 Comment(2)
Is there a half-way point? I'd love to get some ISerializable-like control over some fields, but fall back to the usual machinery for others.Krafftebing
Yes and no, to the half-way point. You can try "DataContractAttribute" with "DataMemberAttribute" on all fields/properties you want to serialize and "IgnoreDataMemberAttribute" on all you don't. There are also Attributes to be used on methods for pre- and postprocessing (de-)serialization, e.g. "OnSerializingAttribute" and "OnDeserializedAttribute". I performed some black magic with that: Serializing an object structure that used classes from dynamically loaded dlls and serializing the dlls alongside for boatstrapping them to load everything again. For that I went to .dll hell.Murder

© 2022 - 2024 — McMap. All rights reserved.