Friday, August 28, 2009

BinaryFormatter: Fields, Properties or Both?

I ran into the second person today who was confused on this concept, so I thought I'd post the answer here. For those of you who missed the question it is: "When I serialize an object, does it only serialize properties, or does it serialize the fields also?".

Well, the answer depends on how you serialize the object. For this post, I'm only going to talk about the BinaryFormatter. XmlSerializer and DataContractSerializer both work differently, reflecting on properties (for XmlSerializer) or properties and fields (for DataContractSerializer). Properties serialized with either the XmlSerializer or the DataContractSerializer will actually call any logic within the properties they're setting. Binary formatter does not. Here's some example code to prove that BinaryFormatter will leave your properties alone:


using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace ConsoleApplication31
{
internal class Program
{
private static void Main()
{
// create an instance of the object
var thing = new StrangeThing();

// set the value.
thing.SetValue(5);
Console.WriteLine("Initial value is {0}", thing.Value);

// serialize our object.
var formatter = new BinaryFormatter();
var stream = new MemoryStream();
formatter.Serialize(stream, thing);
stream.Position = 0;

// Deserialize the object. If this is calling setters, it should throw.
var thing2 = (StrangeThing) formatter.Deserialize(stream);

// Output the result.
Console.WriteLine("After deserialization, the value is {0}", thing2.Value);
Console.WriteLine("Setter was never called");
}
}

[Serializable]
internal class StrangeThing
{
private int _value;

public int Value
{
get { return _value; }
// make the setter throw.
set { throw new NotImplementedException(); }
}

// another method to allow us to set the value.
public void SetValue(int value)
{
_value = value;
}
}
}


The binary formatter establishes the actual "binary" representation of the object. The assumption with binary formatter is that, if the fields are all serialized, the properties will work as expected, because properties are nothing but fancy methods, basically. Thus, the BinaryFormatter only serializes fields, and never properties.

Incidentally, serializing only fields is a great way to make a DataContract in WCF. Should you desire, against my earlier admonitions never to make your business objects data contracts, at least do yourself a favor and never set your properties as DataMembers, only decorate the fields.