Bshox is a binary serialization framework for C# optimized for speed and AOT/Trim compatibility.
It uses a similar syntax existing frameworks like protobuf-net or MessagePack, but instead of using Reflection, Bshox relies exclusively on compile-time code generation for maximum performance and minimal overhead.
- Higher performance and lower memory usage compared to other frameworks (See: benchmarks)
- .NET Standard 2.0 compatible
- Full AOT and Trim support
- No reflection
This uses the same syntax as protobuf-net.
Every type without built-in support must be marked as BshoxContract, and the serialized members as BshoxMember(id). The member ids must be positive and unique.
[BshoxContract]
class MyType
{
[BshoxMember(1)]
public int Id { get; set; }
[BshoxMember(2)]
public float[]? Values { get; set; }
[BshoxMember(3)]
public DateTime CreatedAt { get; set; }
}A partial type marked BshoxSerializer(params types) will contain the logic required to serialize/deserialize the types you specified. Since the Bshox code generator will write that code for you, there is normally no need to add a body.
[BshoxSerializer(typeof(MyType))]
partial class MySerializer;The serializer type has a static Property for every type you specified which contains a Serialize method.
var obj = new MyType
{
Id = 7,
Values = [1.1f, 2.2f, 3.3f],
CreatedAt = DateTime.UtcNow
};
// write to byte array
byte[] array = MySerializer.MyType.Serialize(obj);
// write to stream
using var stream = new MemoryStream();
MySerializer.MyType.Serialize(stream, obj);Deserializing works the same as serializing.
// read from byte array
byte[] data = File.ReadAllBytes("data.bin");
var obj = MySerializer.MyType.Deserialize(data);
// read from stream
using var stream = File.OpenRead("data.bin");
obj = MySerializer.MyType.Deserialize(stream);
stream.Position = 0;
// read from stream asynchronously
obj = await MySerializer.MyType.DeserializeAsync(stream);Member IDs in Bshox function very similar to those in protobuf
- Member IDs must be unique and in the range from 1 to 536870911
- Smaller IDs result in smaller binary data
- Members can be added and removed without breaking compatibility
Here is what Bshox cannot do:
- Reentrancy
- Async serialization/deserialization
The async overload of the Deserialize method simplify buffers the stream asynchronously. The deserialization itself is pure CPU-bound work. - Polymorphism (coming soon™)
- By-ref serialization (maybe in the future)