Today’s topic is Binary serialization, if you wish to read more about serialization or other types of serialization please visit this link:
Binary serialization is type of serialization where type fidelity and reference integrity are preserved, meaning assembly information, private and public fields are being preserved as well as theirs memory locations. You would normally use binary serialization to preserve application state, store it to a backing store (storage medium) and use it later to run application on same computer or maybe multiple other computers.
Hearth of binary serialization is BinaryFormatter class and its Serialize and Deserialize methods. Serialize and Deserialize methods take two parameters stream and object graph and serialize or deserialize object accordingly. Result of serialization are unreadable to human eye but you can read some information:

BinaryFormatter serialization result
As you can see type and field information are preserved.
If you wish serialized data in more readable way you can use SoapFormatter. Note that SoapFormatter is obsolete so use it only for debugging and testing purposes.

SoapFormatter serialization result
To mark a type serializable use Serializable attribute to decorate type. Serializable attribute is not inherited so if you wish to serialize both base and derived class decorate both of them with serializable attribute. Other approach would be to implement ISerializable interface.
If you wish not to serialize filed add NonSerialized attribute.
You can serialize null types, but you can not serialize or deserialize null streams.
Properties are not serialized but their private fields are. Do not serialize auto implemented properties because you cannot guarantee that theirs private fields will have the same name on the other machines as they do on yours.
If we wish more control during Serialization/Deserialization processes we can use attributes from System.Runtime.Serialization and apply them to the methods.
Attributes we can use for methods during serialization:
OnSerializingAttribute – use this attribute to prepare data before deserializing . For example encrypt password field or change distance from miles to kilometers.
OnSerializedAttribute – restores type to a status it was before applying OnSerializingAttribute.
Attributes we can use for methods during serialization:
OnDeserializingAttribute – because serialization cannot use constructor, use this attribute for method that will simulate constructor, and maybe set fields to default values.
OnDeserializedAttribute – use this attribute to manually set value of the fields just after serialization process has finished.
Example for Binary serialization.
We will try to serialize data from Employee class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters.Soap; namespace BinarySerialization { class Program { static void Main(string[] args) { // Data we wish to serialize Employee employee = new Employee() { _employeeId = 1, _employeeName = "JohnDoe", _employeeDepartment = new Department() { _departmentId = 1, _departmentName = "Sales" } }; // We will be reading data from the memory // so it is best to use Memory stream. MemoryStream memoryStream = new MemoryStream(); //Lets start by Serializing data. Stream stream = SerializeData(employee, memoryStream); //Console.WriteLine(new StreamReader(memoryStream).ReadToEnd()); DisplaySerializationResultInConsole(stream); //stream.Position = 0; //And now lets deserialize data Deserialize(stream); Console.ReadKey(); } private static Stream SerializeData(Employee employee, MemoryStream memoryStream) { // To view result in more readable way change // BinaryFormatter type to SoapFormatter //// Lets start by instatiating BinaryFormatter BinaryFormatter binaryFormatter = new BinaryFormatter(); // And let BinaryFormatter.Serialize method do its job binaryFormatter.Serialize(memoryStream, employee); // It is best to rewind stream to 0 position now // so consumer of of stream can consume it right away. memoryStream.Position = 0; //// Uncomment bottom line //// to see the result of serialization //DisplaySerializationResultInConsole(memoryStream); // Stream is ready to be transmitted // So lets send it. return memoryStream; } private static void Deserialize(Stream stream) { // If you have serialized data by using SoapFormatter // change type of binaryFormatter variable to SoapFormatter // Lets start Deserialization process by instantiating BinaryFormatter BinaryFormatter binaryFormatter = new BinaryFormatter(); // BinaryFormatter.Deserialize return object type object employeeObject = binaryFormatter.Deserialize(stream); // As you can see Employee object has been deserialized Employee oldEmployee = employeeObject as Employee; // Proof of Deserialization result: Console.WriteLine("Deserialization result: Employee id:{0}, Employee name: {1}, Department id: {2}, Department name: {3}", oldEmployee._employeeId, oldEmployee._employeeName, oldEmployee._employeeDepartment._departmentId, oldEmployee._employeeDepartment._departmentName); } private static void DisplaySerializationResultInConsole(Stream stream) { Console.WriteLine(new StreamReader(stream).ReadToEnd()); stream.Position = 0; } } [Serializable] public class Employee { public int _employeeId; public string _employeeName; public Department _employeeDepartment; } [Serializable] public class Department { public int _departmentId; public string _departmentName; } } |
Download link for entire solution is here.