Benefits of binary serialization in C#
Manipulationg with object instances using binary serialization in C#
By default object instances in .NET are never "trully" clonned. Instead .NET is doing shallow copy of instances which means if you have one variable which is object instance and you assign that variable to other variable, both of them will point the same instance of that object.
Basically you created two pointers of the same object instance.
The easier way to make a complete clone of object is to serialize and then deserialize it. The p[roblem with serialization is that depending on a type of serialization, some object instances cannot be serialized or you have to write custom code for serailization of the specific object type.
However, binary serialization can serialize pretty much anything as it serializes by transforming all public and private fields of an object to a stream which can be easily stored as an array of bytes.
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; namespace ObjectDeepClone { public static class ExtensionMethods { /// <summary> /// Creates a deep copy of object instance /// </summary> /// <typeparam name="T">Generic type of the object instance being cloned</typeparam> /// <param name="obj">Object instance which needs to be cloned</param> /// <returns>Returns deep copy of object instance</returns> public static T DeepClone<T>(this T obj) where T: class { //If object is not serializable throw an exception if (!typeof(T).IsSerializable) { throw new ArgumentException("The type of object parameter must be serializable.", "obj"); } //If object is null then just return default instance if (Object.ReferenceEquals(obj, null)) { return default(T); } //Setilize and deserialize using binary serialization using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); ms.Position = 0; return (T)formatter.Deserialize(ms); } } } }
This approach for cloning can be also useful if you want to save your object instances as documents. This is the easiest way to save your application work as document.
In case of using binary serialization for storing object instances locally, you have to be careful about changing the class as the binary serialization will fail to de-serialize previously saved document if the class structure was changed in the meanwhile in the application
To make a small test I created a test console application which invokes the following two methods
public static bool SaveObject<T>(this T obj, string filePath) where T : class { using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); ms.Position = 0; File.WriteAllBytes(filePath, ms.ToArray()); return true; } } public static T LoadObject<T>(string filePath) where T : class { if (File.Exists(filePath)) { using (var ms = new MemoryStream(File.ReadAllBytes(filePath))) { var formatter = new BinaryFormatter(); ms.Position = 0; return (T)formatter.Deserialize(ms); } } return null; }
These are basically two parts of DeepClone method. The first one serializes object instance to stream and writes to file and the second one reads bytes, creates memory stream of those bytes and objects instance from them.
using System; namespace ObjectDeepClone { [Serializable] public class TestClonable { public string Name { get; set; } public int Version { get; set; } } class Program { static void Main(string[] args) { var obj = new TestClonable() { Name = "First instance", Version = 1 }; //Create deep clone var deepCopy = obj.DeepClone(); //Save to file deepCopy.SaveObject(@"D:\Temp\object.dat"); //Load from file var loadedObj = ExtensionMethods.LoadObject<TestClonable>(@"D:\Temp\object.dat"); Console.ReadLine(); } } }
References
- https://msdn.microsoft.com/en-us/library/72hyey7b(v=vs.110).aspx
- https://github.com/dejanstojanovic/net-object-deep-copy
- https://github.com/Burtsev-Alexey/net-object-deep-copy
- https://msdn.microsoft.com/en-us/library/system.object.memberwiseclone(v=vs.110).aspx
- https://msdn.microsoft.com/en-us/library/72hyey7b%28v=vs.110%29.aspx
Disclaimer
Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.
Comments for this article