Binary serialization, the smarter way: reloaded
Note: this entry has moved.
VGA posted about a way to improve the binary serialization, by using a compact format. We work together, and I was surprised he didn't post some code for all the code-hungry guys, so here it is:
public sealed class BinaryHelper
{
private enum TypeID : byte
{
Boolean = 0x03,
Byte = 0x06,
...
}
private static Type[] _types;
static IOHelper()
{
_types = new Type[19];
_types[0] = typeof(string);
_types[1] = typeof(int);
_types[2] = typeof(bool);
...
}
private BinaryHelper(){}
public static object ReadBinary(BinaryReader reader)
{
TypeID code = (TypeID) reader.ReadByte();
switch (code)
{
case TypeID.Boolean:
return reader.ReadBoolean();
case TypeID.Byte:
return reader.ReadByte();
...
case TypeID.Object:
BinaryFormatter fmt = new BinaryFormatter();
MemoryStream stm = new MemoryStream(reader.ReadBytes(reader.ReadInt32()));
return fmt.Deserialize(stm);
...
}
}
public static void WriteBinary(BinaryWriter writer, object value)
{
if (value == null)
{
writer.Write((byte)TypeID.Null);
return;
}
Type t = value.GetType();
//Write according to type.
if (t == _types[0])
{
writer.Write((byte)TypeID.String);
writer.Write((String)value);
return;
}
if (t == _types[1])
{
writer.Write((byte)TypeID.Int32);
writer.Write((int)value);
return;
}
...
//Other types serialized to binary directly.
try
{
writer.Write((byte)TypeID.Object);
BinaryFormatter fmt = new BinaryFormatter();
MemoryStream stm = new MemoryStream();
fmt.Serialize(stm, value);
writer.Write(stm.Length);
writer.Write(stm.ToArray());
}
catch (Exception ex)
{
throw new InvalidOperationException("Couldn't serialize object.", ex);
}
}
}
Note that for arbitrary object serialization, the class relies in built-in BinaryFormatter
, which makes it an improvement of if but not a replacement. The types specified in the TypeID enumeration will be highly optimized, and could even expand on the future if you find better ways of serializing other types.
You can figure out the missing parts. It's pretty clear in the IL code (maybe Reflector can help more). What's important is that whether or not you saw System.Web AltSerialization class, this approach is so logic and common that I doubt many more developers haven't arrived to very similar code before (at least I did, even before .NET existed).