Serialization And Deserialization In C# Using Protobuf-net.dll

Protobuf-net is a faster .NET library for serialization and deserialization based on Google's Protocol Buffers. It is designed to be a language neutral, platform neutral, extensible way of serializing structured data for use in communications protocols and efficient data storage (far smaller than xml). You can define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages. It allows you to serialize your .NET objects efficiently and easily. It is compatible .NET 2.0/3.0/3.5/4.0, .NET CF 2.0/3.5, Mono 2.x, Silverlight, etc.
It contains a few attributes which have significance with serializing an object:
  • [ProtoContract]
    ProtoContract is a sealed class which inherits from Attribute class. It needs to be defined above a class and indicates that this class will serialize.

  • [ProtoMember(N)]
    ProtoMember is a sealed class which inherits from Attribute class. It needs to be defined above a property/field and indicates that this field will serialize. Here N represents the number in which order it will serialize. It will start numbering at 1 even if your class uses ProtoMember(N) explicitly on some fields because it serializes in alphabetical order.

  • [ProtoIgnore]
    ProtoContract is a sealed class which inherits from Attribute class. It needs to be defined above a property/field and indicates that this field will ignore (won’t serialize) when serialization occurs. 
Protobuf-net is not compatible with the standard .NET serialization system which means,
  • It ignores the [Serializable] attribute
  • It does not support custom serialization using ISerializable 
We will discuss following points,
  1. Installation of protobuf-net
  2. Serializing an object
  3. Deserialize byte array to an object
  4. Advantages of protobuf-net
To install protobuf-net, you need to use NuGet Package Manager which provides the latest version of the dll. Follow Figure 1 which shows how to install the dll.
                Figure 1: Install through Nuget Package Manager
TOOLS -> Library Package Manager -> Package Manager Console
Install-Package protobuf-net

If you are using VS 2012/2013 or lower, then you need to provide version in command.
Install-Package protobuf-net -Version
Before starting demonstration, we need to decorate the entity. Let's say Project is the entity which has two fields, ID and Name. ProtoContract attribute defines to make class serializable and Protomember defines to make members/properties as serializable.
  1. [ProtoContract(SkipConstructor = true)]  
  2. public class Project  
  3. {  
  4.     [ProtoMember(1)]  
  5.     public int ID { getset; }  
  7.     [ProtoMember(2)]  
  8.     public string Name { getset; }  

Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, database or file. Its aim is to save the state of an object in order to be able to recreate it in the future when needed. The below code-snippet defines a method (ProtoSerialize()) which receives an object. Then it calls Serialize() to convert the object to a stream of bytes through MemoryStream object.
  1. public static byte[] ProtoSerialize<T>(T record) where T : class  
  2. {  
  3.     if (null == record) return null;  
  5.     try  
  6.     {  
  7.         using (var stream = new MemoryStream())  
  8.         {  
  9.             Serializer.Serialize(stream, record);  
  10.             return stream.ToArray();  
  11.         }  
  12.     }  
  13.     catch  
  14.     { 
  15.         // Log error
  16.         throw;  
  17.     }  

The following figure shows the result after Serialization has happened. It converts the Project object to bytes array through ProtoSerialize() method.

Figure 2: Result after Serialization
Deserialization is the process of converting streams of bytes into an object. It is the reverse process of Serialization (discussed above). The below code-snippet defines Deserialize method(ProtoDeserialize()) with byte array as parameter. Then it converts byte array to MemoryStream object. Next it calls Deserialize() with passing MemoryStream object as parameter and it returns an actual object.
  1. public static T ProtoDeserialize<T>(byte[] data) where T : class  
  2. {  
  3.     if (null == data) return null;  
  5.     try  
  6.     {  
  7.         using (var stream = new MemoryStream(data))  
  8.         {  
  9.             return Serializer.Deserialize<T>(stream);  
  10.         }  
  11.     }  
  12.     catch  
  13.     { 
  14.         // Log error
  15.         throw;  
  16.     }  

The following figure shows the result after Deserialization has happened. It converts the bytes array to Project object through ProtoDeserialize() method.
Figure 3: Result after Deserialization
  • Very fast processing
  • Hard to decode without knowing schema
  • Very useful for internal APIs
  • Easy Language Interoperability
  • Generic request/response allows more flexibility 
Performance comparison
Figure 4: Serialization Performance graph of libraries
In this article, we discussed about serialization and deserialization using protobuf-net dll. We can perform the same functionality in different ways like DataContractSerializer, JSON.NET, JavaScriptSerializer etc. However, protobuf-net provides better performance as compared to other methods. So use protobuf-net dll whenever you develop internal APIs and perform serialization/deserialization.