Home

Awesome

Apex.Serialization

A high performance contract-less binary serializer capable of handling data trees or object graphs.

Suitable for realtime workloads where the serialized data will not persist for long, as most assembly changes will render the data format incompatible with older versions. Performance is optimized for throughput at the expense of initialization time.

Status

Build Status <!-- [![Tests](https://img.shields.io/azure-devops/tests/numenfall/Libraries/11.svg?compact_message)](https://numenfall.visualstudio.com/Libraries/_build/latest?definitionId=11&branchName=master) --> Code Coverage

Nuget Package

Using the latest package version is recommended, but 1.3.4 is the latest version that supportes netstandard or .NET framework targets.

Use Cases

Good

Bad

Limitations

As the serialization is contract-less, the binary format produced depends on precise characteristics of the types serialized. Most changes to types, such as adding or removing fields, renaming types, or changing relationships between types will break compatibility with previously serialized data. Serializing and deserializing between different chip architectures and .NET runtimes is not supported.

For performance reasons, the serializer and deserializer make use of pointers and direct memory access. This will often cause attempting to deserialize incompatible data to immediately crash the application instead of throwing an exception.

NEVER deserialize data from an untrusted source.

Some types aren't supported:

Requires code generation capabilities

Migrating to version 2.x

Version 2 adds type whitelisting, which means no types can be serialized unless marked by calling Settings.MarkSerializable(Type | Func<Type, bool>). To restore the previous behavior for backwards compatibility you can simply pass a function that always returns true.

Usage

Serialization

var obj = ClassToSerialize();
var binarySerializer = Binary.Create(new Settings().MarkSerializable<ClassToSerializeType>());
binarySerializer.Write(obj, outputStream);

Deserialization

var obj = binarySerializer.Read<SerializedClassType>(inputStream)

Class instances are not thread safe, static methods are thread safe unless otherwise noted in their documentation.

Always reuse serializer instances when possible, as the instance caches a lot of data to improve performance when repeatedly serializing or deserializing objects. Since the instances are not thread-safe, you should use an object pool or some other method to ensure that only one thread uses an instance at a time.

Fields with the [Nonserialized] attribute will not be serialized or deserialized.

Settings

You must pass a Settings object to Binary.Create that lets you choose:

Performance

Performance is a feature! Apex.Serialization is an extremely fast binary serializer. See benchmarks for comparisons with other fast binary serializers.

Custom serialization/deserialization

You can define custom serialization and deserialization simply by calling

Settings.RegisterCustomSerializer<CustomType>(writeAction, readAction)

In order for custom serialization to be used, the SupportSerializationHooks property on the Settings used to instantiate the Binary class must also be set to true.

Both the write Action and read Action will be called with an instance of the type being serialized/deserialized and a BinaryWriter/BinaryReader interface which exposes three methods:

        void Write(string input);
        void Write<T>(T value) where T : struct;
        void WriteObject<T>(T value);

The Actions can optionally take a third parameter for context, which is set on the Binary instance with SetCustomHookContext.

The reader has corresponding methods for reading back the values. Behavior of the generic Write/Read method when passed a non-primitive is undefined. If multiple customer serializers match an object, they will all be called in the order in which they were registered.

Tips for best performance