Serialization with protobuf-net
protobuf-net is an open source .net implementation of Google's protocol buffer binary serialization format.
Consider the following classes, I have included a sub-class to make it slightly more than a non-trivial example
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public DateTime DateOfBirth { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Number { get; set; }
public string StreetName { get; set; }
}
public class ExtendedAddress : Address
{
public string BuildingName { get; set; }
}
With v2 of protobuf-net
you can build a serializer on the fly which means you don't have to decorate the classes with attributes:
var protobufModel = ProtoBuf.Meta.TypeModel.Create();
AddTypeToModel<Person>(protobufModel);
AddTypeToModel<Address>(protobufModel).AddSubType(500, typeof(ExtendedAddress));
AddTypeToModel<ExtendedAddress>(protobufModel);
private MetaType AddTypeToModel<T>(RuntimeTypeModel typeModel)
{
var properties = typeof(T).GetProperties().Select(p => p.Name).ToArray();
return typeModel.Add(typeof(T), true).Add(properties);
}
While this method is effective it is considered brittle if the class changes. What would happen if we added a property Lot
property to the Address
class?
This would break the backwards compatibility of any previously serialized data as protobuf-net
is assigning ids to each serialized field.
If we added a new property Suburb
which is alphabetically after StreetName
then everything would (luckily) work.
The moral of the story is only use this method if your class isn't going to change (sure!) or you dont care about backwards compatibility.
Instead, decorate your classes:
public class Person
{
[ProtoMember(1)]
public string Name { get; set; }
[ProtoMember(2)]
public int Age { get; set; }
[ProtoMember(3)]
public DateTime DateOfBirth { get; set; }
[ProtoMember(4)]
public Address Address { get; set; }
}
[ProtoInclude(500, typeof(ExtendedAddress))]
public class Address
{
[ProtoMember(1)]
public string Number { get; set; }
[ProtoMember(2)]
public string StreetName { get; set; }
}
public class ExtendedAddress : Address
{
[ProtoMember(1)]
public string BuildingName { get; set; }
}
protobuf-net
also respects DataContract
and DataMember
attributes in the System.Runtime.Serialization
namespace if you want to use them instead or if you class is attributed already.
Last revised: 03 Nov, 2011 03:05 PM History
No new comments are allowed on this post.
Comments
No comments yet. Be the first!