Skip to content

Example Formatter: Keep the IEqualityComparer of a collection

Rikimaru edited this page Feb 15, 2019 · 1 revision

This example shows a formatter that keeps the Comparer of a collection through the serialization.

Right now it only handles a HashSet<byte[]>, but you can easily also make it work for the generic case HashSet<T> (by simply changing all byte[] to T).

class HashSetFormatterThatKeepsItsComparer : IFormatter<HashSet<byte[]>>
{
	// Sub-formatters are automatically set by Ceras' dependency injection
	IFormatter<byte[]> _byteArrayFormatter;
	IFormatter<IEqualityComparer<byte[]>> _comparerFormatter; // auto-implemented by Ceras using DynamicObjectFormatter

	public void Serialize(ref byte[] buffer, ref int offset, HashSet<byte[]> set)
	{
		// What do we need?
		// - The comparer
		// - Number of entries
		// - Actual content

		// Comparer
		_comparerFormatter.Serialize(ref buffer, ref offset, set.Comparer);

		// Count
		// We could use a 'IFormatter<int>' field, but Ceras will resolve it to this method anyway...
		SerializerBinary.WriteInt32(ref buffer, ref offset, set.Count);

		// Actual content
		foreach (var array in set)
			_byteArrayFormatter.Serialize(ref buffer, ref offset, array);
	}

	public void Deserialize(byte[] buffer, ref int offset, ref HashSet<byte[]> set)
	{
		IEqualityComparer<byte[]> equalityComparer = null;
		_comparerFormatter.Deserialize(buffer, ref offset, ref equalityComparer);

		// We can already create the hashset
		set = new HashSet<byte[]>(equalityComparer);

		// Read content...
		int count = SerializerBinary.ReadInt32(buffer, ref offset);
		for (int i = 0; i < count; i++)
		{
			byte[] ar = null;
			_byteArrayFormatter.Deserialize(buffer, ref offset, ref ar);

			set.Add(ar);
		}
	}
}

In the old version (v3.x.x) you can use it like this:

SerializerConfig config = new SerializerConfig();

config.OnResolveFormatter.Add((c, t) =>
{
    if (t == typeof(HashSet<byte[]>))
        return new HashSetFormatterThatKeepsItsComparer();
    return null; // continue searching
});

In the new version (v4) it's even easier:

config.ConfigType<HashSet<byte[]>>()
      .SetFormatter(new HashSetFormatterThatKeepsItsComparer());

If you have any questions, feel free to open an issue or join the discord sever :)

Clone this wiki locally