Antmicro Migrant is available from here:
https://github.com/antmicro/Migrant
To get started do the following steps:
1. Create a new console application in Visual Studio:
2. Install the ‘Migrant’ NuGet package
Select Tools > NuGet Package Manager > Package Manager Console:
Install Migrant by typing ‘install-package migrant’
3. A simple serialization example.
Modify your Program.cs to perform a basic serialize / deserialize example as shown:
using System;
using System.IO;
using Antmicro.Migrant;
namespace MigrantSerialize
{
internal class Program
{
private static void Main(string[] args)
{
var serializer = new Serializer();
var stream = new MemoryStream();
var obj = new MyClass
{
Name = "XYZ", Value = 111
};
serializer.Serialize(obj, stream);
stream.Seek(0, SeekOrigin.Begin);
var deserializedObj = serializer.Deserialize<MyClass>(stream);
Console.WriteLine("De-serialised object: \n");
Console.WriteLine("Name: " + deserializedObj.Name + "\nValue: " + deserializedObj.Value);
}
#region Nested type: MyClass
public class MyClass
{
public string Name { get; set; }
public int Value { get; set; }
}
#endregion
}
}
Giving the following output:
4. An example using FileStream to serialize/de-serialize a collection of objects
using System;
using System.Collections.Generic;
using System.IO;
using Antmicro.Migrant;
namespace MigrantSerialize
{
internal class Program
{
private static void Main(string[] args)
{
var serializer = new Serializer();
const string FilePath = @"C:\temp\text.txt";
if (File.Exists(FilePath))
{
File.Delete(FilePath);
}
var stream = File.Create(FilePath);
var objects = new List<MyClass>
{
new MyClass
{
Name = "ABC", Value = 321
},
new MyClass
{
Name = "XYZ", Value = 222
},
new MyClass
{
Name = "IJK", Value = 101
}
};
serializer.Serialize(objects, stream);
stream.Seek(0, SeekOrigin.Begin);
var deserializedObj = serializer.Deserialize<IEnumerable<MyClass>>(stream);
Console.WriteLine("De-serialised objects: \n");
foreach (var deserializedObject in objects)
{
Console.WriteLine("Name: " + deserializedObject.Name + "\tValue: " + deserializedObject.Value);
}
}
#region Nested type: MyClass
public class MyClass
{
public string Name { get; set; }
public int Value { get; set; }
}
#endregion
}
}
Giving the following output:
5. Serializing and de-serializing a tree-like data structure
Migrant does the job on tree structures too. In this example a ‘TreeNode’ data structure that contains a list of ‘TreeNode’ structures. TreeNode also contains a method to recursively print its contents as well, indenting the node names by the level of recursion:
using Antmicro.Migrant;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MigrantSerialize
{
public class TreeNode
{
public string Name { get; set; }
public List<TreeNode> Children = new List<TreeNode>();
public void Print(TreeNode node, int level)
{
if (level == 1)
{
Console.WriteLine(node.Name);
}
if (node.Children == null)
return;
foreach (var childNode in node.Children)
{
var textWithPadding = childNode.Name.PadLeft(level * 4, ' ');
Console.WriteLine(textWithPadding);
Print(childNode, level + 1);
}
}
}
internal class Program
{
private static void Main(string[] args)
{
var serializer = new Serializer();
const string FilePath = @"C:\temp\text.txt";
if (File.Exists(FilePath))
{
File.Delete(FilePath);
}
var stream = File.Create(FilePath);
var node1 = new TreeNode { Name = "A" };
var node2 = new TreeNode { Name = "B" };
var node3 = new TreeNode { Name = "C" };
var node4 = new TreeNode { Name = "D" };
var node5 = new TreeNode { Name = "E" };
var node6 = new TreeNode { Name = "F" };
var children1 = new List<TreeNode>() { node1, node2, node3 };
var children2 = new List<TreeNode>() { node4, node5 };
var children3 = new List<TreeNode>() { node6 };
var root = new TreeNode { Name = "Root" };
node5.Children = children3;
node2.Children = children2;
root.Children = children1;
serializer.Serialize(root, stream);
stream.Seek(0, SeekOrigin.Begin);
var deserializedObj = serializer.Deserialize<TreeNode>(stream);
Console.WriteLine("De-serialised tree structure: \n");
deserializedObj.Print(deserializedObj, 1);
}
}
}
Giving the following output:
6. Customising the settings
As an example, you may want to allow for differences in GUID -that can result from different compilations of the same library.
Without setting the version tolerance level your program will probably throw an exception when you re-compile the same code and try to de-serialize the same data file again, precisely because of the mismatch in GUIDs:
Antmicro.Migrant.VersionTolerance.VersionToleranceException was unhandled
HResult=-2146233088
Message=The class MigrantSerialize.Program+MyClass was serialized with different module version id d6fdaf08-263b-4789-bcc0-372b532d05f6, current one is b1e6b693-a4f4-4a2d-9aad-738eb43cc831.
Source=Migrant
To overcome this you can set the VersionToleranceLevel enum to allow for GUID changes:
const VersionToleranceLevel VersionToleranceLevel = VersionToleranceLevel.AllowGuidChange;
and use this when creating your custom settings for serialization/deserialization and version tolerance levels:
var customSettings = new Settings(Method.Generated, Method.Generated, VersionToleranceLevel);
Full code listing shown, that uses the version tolerance. Using this you can re-compile and re-run without the exception:
using System;
using System.IO;
using Antmicro.Migrant;
using Antmicro.Migrant.Customization;
namespace MigrantSerialize
{
internal class Program
{
public const string FilePath = @"E:\temp\datafile.dat";
private static void Main(string[] args)
{
var obj = new MyClass
{
Key = "XYZ", Value = 111,
};
Serialize(obj);
Deserialize();
}
private static Settings CustomSettings { get; set; }
#region Nested type: MyClass
public class MyClass
{
public string Key { get; set; }
public int Value { get; set; }
}
#endregion
public static void Serialize(object obj)
{
if (File.Exists(FilePath))
{
return;
}
var serializer = new Serializer();
using (var stream = File.Create(FilePath))
{
serializer.Serialize(obj, stream);
stream.Seek(0, SeekOrigin.Begin);
}
}
public static void Deserialize()
{
const Method SerializationMethod = Method.Generated;
const Method DeserializationMethod = Method.Generated;
const VersionToleranceLevel VersionToleranceLevel = VersionToleranceLevel.AllowGuidChange;
var settings = new Settings(SerializationMethod, DeserializationMethod, VersionToleranceLevel);
var deserializer = new Serializer(settings);
using (var stream = File.OpenRead(FilePath))
{
var deserializedObj = deserializer.Deserialize<MyClass>(stream);
Console.WriteLine("De-serialised object: \n");
Console.WriteLine("Key: " + deserializedObj.Key + "\nValue: " + deserializedObj.Value);
}
}
}
}






