Salar.Bois.CodeGen 4.0.0

dotnet add package Salar.Bois.CodeGen --version 4.0.0
                    
NuGet\Install-Package Salar.Bois.CodeGen -Version 4.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Salar.Bois.CodeGen" Version="4.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Salar.Bois.CodeGen" Version="4.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Salar.Bois.CodeGen" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Salar.Bois.CodeGen --version 4.0.0
                    
#r "nuget: Salar.Bois.CodeGen, 4.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Salar.Bois.CodeGen@4.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Salar.Bois.CodeGen&version=4.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Salar.Bois.CodeGen&version=4.0.0
                    
Install as a Cake Tool

Salar.Bois is the most compact, extermly fast binary serializer for .Net Standard, .NET Code and .NET Framework.

  • No compression is done, the high compact ratio is the result of Bois format.
  • No configuration.
  • No change to your classes.
  • Compression is provided as a seperate package.

Why Salar.Bois?

  • Because payload size matters. Bois serializer generates the smallest payload size.
  • Because speed matters. Both serialization and deserialization are extremely fast.
  • Easy to use, Serialize<T> and Deserialize<T> are all you need.
  • No configuration required. No separate schema required.

NuGet Packages

Source code generator package

PM> Install-Package Salar.Bois.CodeGen

Dynamic serializer package

PM> Install-Package Salar.Bois

LZ4 Compression wrapper package

PM> Install-Package Salar.Bois.LZ4

Minimum frameworks supported are .NET Framework 4.8 , .NET 6.0 and up to latest .NET 10.0

Getting Started with Source generator

The Salar.Bois.CodeGen package provides the source code generator version of Bois. Instead of using the BoisSerializer class at runtime, you declare a static partial class that hosts the read and write methods as static partial methods. The generator creates the method body during compilation.

To use it, add the Salar.Bois.CodeGen package to your project and create a static partial class to host your serializer methods. Mark read methods with [BoisReader] and write methods with [BoisWriter].

The serializer class must be partial, and every generated method must also be partial. This is how the compiler connects your method declarations with the generated implementations. If the class or methods are not partial, source generation cannot complete the methods.

Important: source generated partial methods with accessibility require C# 9.0 or later. If your project uses an older C# language version, set <LangVersion>9.0</LangVersion> or a newer version in your project file.

You can then call these methods like normal methods. There is no need to create a BoisSerializer instance for this generated path.

using Salar.BinaryBuffers;
using Salar.Bois.CodeGen;
using System;
using System.IO;
using System.Text;

public static partial class CustomerOrderSerializer
{
	// ... other signatures ...
	
	[BoisReader]
	public static partial CustomerOrder? ReadCustomerOrder(Stream source);

	[BoisWriter]
	public static partial void WriteCustomerOrder(CustomerOrder? order, Stream output);

	[BoisReader]
	public static partial CustomerOrder? ReadCustomerOrder(byte[] buffer, int position, int length);

	[BoisWriter]
	public static partial void WriteCustomerOrder(CustomerOrder? order, byte[] buffer, int position, int length);

	// ... other signatures ...
}

Sample usage:

using (var file = new FileStream("output.data", FileMode.Create))
{
	CustomerOrderSerializer.WriteCustomerOrder(order, file);
}

using (var file = new FileStream("output.data", FileMode.Open))
{
	var order = CustomerOrderSerializer.ReadCustomerOrder(file);
}

You can also use an existing byte array buffer. This is useful when your application already owns the memory and you want to avoid creating an extra stream.

var buffer = new byte[4096];

CustomerOrderSerializer.WriteCustomerOrder(order, buffer, 0, buffer.Length);

var restoredOrder = CustomerOrderSerializer.ReadCustomerOrder(buffer, 0, buffer.Length);

Generated methods use BoisCodeGen.DefaultEncoding when an Encoding argument is not supplied. It defaults to UTF-8 and can be configured during application startup.

BoisCodeGen.DefaultEncoding = Encoding.UTF8;

The generated methods support stream based input and output. They also support buffer reader and buffer writer overloads, byte array overloads, array segment overloads for reading, and byte array overloads with position and length when you want to work directly with an existing buffer.

Method code generation is good for performance because the serializer code is created at compile time. There is no first use cost for building serializers at runtime, and there is no reflection based initialization step before the first serialization call. This also makes the package suitable for NativeAOT, where runtime code generation is not available.

Supported method signatures:

using Salar.BinaryBuffers;
using Salar.Bois.CodeGen;
using System;
using System.IO;
using System.Text;

public static partial class CustomerOrderSerializer
{
	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrder(Stream source);

	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrder(Stream source, Encoding encoding);

	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrder(BufferReaderBase reader);

	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrder(BufferReaderBase reader, Encoding encoding);

	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrder(byte[] buffer);

	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrder(byte[] buffer, Encoding encoding);

	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrder(ArraySegment<byte> bytes);

	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrder(ArraySegment<byte> bytes, Encoding encoding);

	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrderIn(in ArraySegment<byte> bytes);

	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrderIn(in ArraySegment<byte> bytes, Encoding encoding);

	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrder(byte[] buffer, int position, int length);

	[BoisReader]
	public static partial CustomerOrder ReadCustomerOrder(byte[] buffer, int position, int length, Encoding encoding);

	[BoisWriter]
	public static partial void WriteCustomerOrder(CustomerOrder order, Stream output);

	[BoisWriter]
	public static partial void WriteCustomerOrder(Stream output, CustomerOrder order);

	[BoisWriter]
	public static partial void WriteCustomerOrder(CustomerOrder order, Stream output, Encoding encoding);

	[BoisWriter]
	public static partial void WriteCustomerOrder(Stream output, CustomerOrder order, Encoding encoding);

	[BoisWriter]
	public static partial void WriteCustomerOrder(CustomerOrder order, BufferWriterBase writer);

	[BoisWriter]
	public static partial void WriteCustomerOrder(BufferWriterBase writer, CustomerOrder order);

	[BoisWriter]
	public static partial void WriteCustomerOrder(CustomerOrder order, BufferWriterBase writer, Encoding encoding);

	[BoisWriter]
	public static partial void WriteCustomerOrder(BufferWriterBase writer, CustomerOrder order, Encoding encoding);

	[BoisWriter]
	public static partial void WriteCustomerOrder(CustomerOrder order, byte[] buffer, int position, int length);

	[BoisWriter]
	public static partial void WriteCustomerOrder(byte[] buffer, int position, int length, CustomerOrder order);

	[BoisWriter]
	public static partial void WriteCustomerOrder(CustomerOrder order, byte[] buffer, int position, int length, Encoding encoding);

	[BoisWriter]
	public static partial void WriteCustomerOrder(byte[] buffer, int position, int length, CustomerOrder order, Encoding encoding);
}

Getting Started with dynamic BoisSerializer

It is easy to use , just add the package to your project and voila, you can now use it.

All you need to do is to call Serialize method.

BoisSerializer.Initialize<Person>();
var boisSerializer = new BoisSerializer();

using (var mem = new MemoryStream())
{
	boisSerializer.Serialize(personInstance, mem);

	return mem.ToArray();
}

Note: Calling BoisSerializer.Initialize is not required at all, but if the performance of application is important to you, it is better to do it at the begining of your application.

Here is the complete example:

public class Project
{
	public int ID { get; set; }
	public string Name { get; set; }
	public string Description { get; set; }
	public string ProjectUrl { get; set; }
	public Version Version { get; set; }
}

class Program
{
	static void Main()
	{
		// Initialize is optional, but recommended for better performance
		BoisSerializer.Initialize<Project>();

		var projectInstance = new Project()
		{
			ID = 1,
			Name = "Salar.Bois",
			ProjectUrl = "https://github.com/salarcode/Bois",
			Version = new Version(3, 0, 0, 0),
			Description = "Salar.Bois is a compact, fast and powerful binary serializer for .NET Framework."
		};

		var boisSerializer = new BoisSerializer();

		using (var file = new FileStream("output.data", FileMode.Create))
		{
			boisSerializer.Serialize(projectInstance, file);
		}

		// All done.

		// ...
		// if you want to have more compression using LZ4 wrapper

		var boisLz4Serializer = new BoisLz4Serializer();

		using (var file = new FileStream("output-compressed.data", FileMode.Create))
		{
			boisLz4Serializer.Pickle(projectInstance, file);
		}

	}
}

How to deserialize an object:

var boisSerializer = new BoisSerializer();
return boisSerializer.Deserialize<Project>(dataStream);

// and the compressed data
var boisLz4Serializer = new BoisLz4Serializer();
return boisLz4Serializer.Unpickle<Project>(dataStream);

Defining objects

Nothing special is really required. Just these small easy rules.

  • Having parameter-less public constructor.
  • Collections/Lists should be generic and implement one of ICollection<>, IList<> or IDictionary<>

Compression

The BoisLz4Serializer class is in a separate package called Salar.Bois.LZ4. It is provided for anyone looking for more compact serialization. To use it just create a new instance of BoisLz4Serializer and to serialize and compress the objects call Pickle and to deserialize and uncompress call Unpickle. Please note that BoisLz4Serializer -for now- is implemented as a wrapper around LZ4.

Bois Format

If you are interested to know how Salar.Bois has gain this amazing compact format check out its Bois format wiki page.

Bois Format Schema.

Benchmarks

The benchmarks sourcecode is available. Every elapsed time is calculated for 5000 iteration (v3.0).

Please note that in these tests no configuration required for Bois versus attributes required for Avro, Zero, MsPack and ProtoZBuff. Also Zero required the properties to be virtual.

-Serialization against: ArrayTypes with small data

Serializer Payload Size (bytes) Serialization Deserialization Format Note
Salar.Bois 58 6 ms 5 ms Binary
Salar.Bois.LZ4 59 25 ms 6 ms Binary
Microsoft.Avro 87 9 ms 10 ms Binary
MessagePack 127 4 ms 4 ms Binary
MessagePackLZ4 125 18 ms 5 ms Binary
protobuf-net 92 7 ms 12 ms Binary
BinaryFormatter 458 59 ms 48 ms Binary
ZeroFormatter 153 3 ms 1 ms Binary

-Serialization against: ArrayTypes with big data

Serializer Payload Size (bytes) Serialization Deserialization Format Note
Salar.Bois 1400 70 ms 73 ms Binary
Salar.Bois.LZ4 1342 117 ms 75 ms Binary
Microsoft.Avro 1709 89 ms 119 ms Binary
MessagePack 1951 19 ms 28 ms Binary
MessagePackLZ4 1593 57 ms 41 ms Binary
protobuf-net 2161 58 ms 79 ms Binary
BinaryFormatter 2641 52 ms 50 ms Binary
ZeroFormatter 2336 11 ms 1 ms Binary

-Serialization against: PrimitiveTypes with small data

Serializer Payload Size (bytes) Serialization Deserialization Format Note
Salar.Bois 74 3 ms 4 ms Binary
Salar.Bois.LZ4 75 19 ms 5 ms Binary
Microsoft.Avro 77 4 ms 3 ms Binary
MessagePack 161 7 ms 3 ms Binary
MessagePackLZ4 173 22 ms 3 ms Binary
protobuf-net 91 6 ms 7 ms Binary
BinaryFormatter 671 72 ms 79 ms Binary
ZeroFormatter 134 7 ms 0 ms Binary

-Serialization against: ComplexCollections with small data

Serializer Payload Size (bytes) Serialization Deserialization Format Note
Salar.Bois 82 14 ms 23 ms Binary
Salar.Bois.LZ4 81 30 ms 24 ms Binary
Microsoft.Avro - - - Binary Error
MessagePack 171 27 ms 19 ms Binary
MessagePackLZ4 153 42 ms 21 ms Binary
protobuf-net 150 17 ms 34 ms Binary
BinaryFormatter 10852 636 ms 612 ms Binary
ZeroFormatter - - - Binary Not supported

-Serialization against: ComplexCollections with big data

Serializer Payload Size (bytes) Serialization Deserialization Format Note
Salar.Bois 10414 356 ms 411 ms Binary
Salar.Bois.LZ4 7628 837 ms 483 ms Binary
Microsoft.Avro - - - Binary Error
MessagePack 11013 796 ms 301 ms Binary
MessagePackLZ4 7636 28 ms 390 ms Binary
protobuf-net 14865 7 ms 265 ms Binary
BinaryFormatter 34751 961 ms 488 ms Binary
ZeroFormatter - - - Binary Not supported

-Serialization against: ComplexContainer Collections

Serializer Payload Size (bytes) Serialization Deserialization Format Note
Salar.Bois 120 9 ms 11 ms Binary
Salar.Bois.LZ4 114 27 ms 12 ms Binary
Microsoft.Avro - - - Binary Not supported
MessagePack - - - Binary Not supported
protobuf-net 171 14 ms 24 ms Binary
BinaryFormatter 7396 379 ms 475 ms Binary
ZeroFormatter - - - Binary Not supported

-Serialization against: SpecializedCollections

Serializer Payload Size (bytes) Serialization Deserialization Format Note
Salar.Bois 28 9 ms 17 ms Binary
Salar.Bois.LZ4 29 22 ms 17 ms Binary
Microsoft.Avro - - - Binary Invalid Result
MessagePack - - - Binary Not supported
MessagePackLZ4 - - - Binary Not supported
protobuf-net - - - Binary Not supported
BinaryFormatter 2515 763 ms 285 ms Binary
ZeroFormatter - - - Binary Not supported
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
4.0.0 43 7/15/2026

Adds the BOIS source-code-generation serializer package with generated reader and writer support.