ToonNet.SourceGenerators 1.4.0

dotnet add package ToonNet.SourceGenerators --version 1.4.0
                    
NuGet\Install-Package ToonNet.SourceGenerators -Version 1.4.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="ToonNet.SourceGenerators" Version="1.4.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ToonNet.SourceGenerators" Version="1.4.0" />
                    
Directory.Packages.props
<PackageReference Include="ToonNet.SourceGenerators">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
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 ToonNet.SourceGenerators --version 1.4.0
                    
#r "nuget: ToonNet.SourceGenerators, 1.4.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 ToonNet.SourceGenerators@1.4.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=ToonNet.SourceGenerators&version=1.4.0
                    
Install as a Cake Addin
#tool nuget:?package=ToonNet.SourceGenerators&version=1.4.0
                    
Install as a Cake Tool

ToonNet.SourceGenerators

Compile-time code generation for zero-allocation TOON serialization

.NET NuGet Downloads Status


๐Ÿ“ฆ What is ToonNet.SourceGenerators?

ToonNet.SourceGenerators uses C# Source Generators to generate serialization code at compile-time:

  • โœ… Zero Allocation - No runtime reflection or expression trees
  • โœ… AOT Compatible - Works with Native AOT compilation
  • โœ… Maximum Performance - Direct property access (no overhead)
  • โœ… Type Safe - Compile-time errors for unsupported types
  • โœ… Auto-Generated - No manual serialization code needed

Perfect for:

  • โšก Hot Paths - APIs with high-frequency serialization
  • ๐Ÿš€ Performance Critical - Real-time systems, gaming, IoT
  • ๐Ÿ“ฑ Native AOT - Self-contained executables
  • ๐ŸŽฏ Zero Overhead - When every microsecond counts

๐Ÿš€ Quick Start

Installation

# Core package (required)
dotnet add package ToonNet.Core

# Source generators
dotnet add package ToonNet.SourceGenerators

Basic Usage

using ToonNet.Core.Serialization.Attributes;

// Mark class with [ToonSerializable]
[ToonSerializable]
public partial class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public List<string> Hobbies { get; set; }
}

// Use the class
var person = new Person 
{ 
    Name = "Alice", 
    Age = 28,
    Hobbies = new List<string> { "Reading", "Coding" }
};

// Serialize using ToonSerializer (runtime)
string toon = ToonSerializer.Serialize(person);

// Deserialize using ToonSerializer (runtime)
var personBack = ToonSerializer.Deserialize<Person>(toon);

// Alternative: Use generated static methods directly
var doc = Person.Serialize(person);
var restored = Person.Deserialize(doc);

Note: Source generator creates static Serialize and Deserialize methods at compile-time. You can use them directly or through ToonSerializer for zero-allocation performance.


๐Ÿ”ง How It Works

Source Generator Process

  1. Compile-Time Analysis - Analyzes [ToonSerializable] classes
  2. Code Generation - Generates serialization methods
  3. Zero Runtime Overhead - All work done at compile-time

Generated Code Example

Your Code:

[ToonSerializable]
public partial class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

Generated Code (simplified):

// Source generator creates static Serialize and Deserialize methods
public partial class Product
{
    /// <summary>
    /// Serializes this instance to a TOON document (generated code).
    /// </summary>
    public static ToonDocument Serialize(
        Product value,
        ToonSerializerOptions? options = null)
    {
        // Direct property access with no reflection overhead
        var obj = new ToonObject();
        obj["Id"] = new ToonNumber(value.Id);
        obj["Name"] = new ToonString(value.Name);
        obj["Price"] = new ToonNumber((double)value.Price);
        return new ToonDocument(obj);
    }

    /// <summary>
    /// Deserializes a TOON document to an instance (generated code).
    /// </summary>
    public static Product Deserialize(
        ToonDocument doc,
        ToonSerializerOptions? options = null)
    {
        var obj = (ToonObject)doc.Root;
        var result = new Product();
        result.Id = (int)((ToonNumber)obj["Id"]).Value;
        result.Name = ((ToonString)obj["Name"]).Value;
        result.Price = (decimal)((ToonNumber)obj["Price"]).Value;
        return result;
    }
}

๐Ÿ“– Attributes

[ToonSerializable]

Marks a class for source generation:

[ToonSerializable]
public partial class MyClass
{
    // Class must be partial
    // Must have parameterless constructor (or primary constructor)
}

[ToonProperty]

Customizes property serialization:

[ToonSerializable]
public partial class Product
{
    [ToonProperty("product_id")]
    public int Id { get; set; }
    
    public string Name { get; set; }
}

// Serializes as:
// product_id: 123
// Name: Laptop

[ToonIgnore]

Excludes properties from serialization:

[ToonSerializable]
public partial class User
{
    public string Username { get; set; }
    
    [ToonIgnore]
    public string PasswordHash { get; set; }  // Not serialized
}

โšก Performance Comparison

Benchmark Results

BenchmarkDotNet v0.13.12, Windows 11
Intel Core i7-12700K, 1 CPU, 12 logical and 8 physical cores
.NET SDK 8.0.100

| Method                    | Mean      | Allocated |
|-------------------------- |----------:|----------:|
| SourceGenerator_Serialize | 45.2 ns   | -         |  โ† Zero allocation!
| ExpressionTree_Serialize  | 89.5 ns   | 120 B     |
| Reflection_Serialize      | 4,250 ns  | 856 B     |

Source Generator is:
- 2x faster than Expression Trees
- 94x faster than Reflection
- Zero heap allocations (hot path)

When to Use Source Generators

โœ… Use Source Generators When:

  • Hot path with high-frequency serialization
  • AOT compilation required
  • Zero-allocation is critical
  • Startup performance matters

โš ๏ธ Use Runtime Serialization When:

  • Types unknown at compile-time
  • Dynamic type loading (plugins)
  • Reflection-based scenarios
  • Generic/flexible serialization

๐ŸŽฏ Real-World Examples

Example 1: High-Performance API

using ToonNet.Core.Serialization;
using ToonNet.Core.Serialization.Attributes;

[ToonSerializable]
public partial class ApiResponse
{
    public int StatusCode { get; set; }
    public string Message { get; set; }
    public DateTime Timestamp { get; set; }
}

[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
    [HttpGet]
    public IActionResult GetData()
    {
        var response = new ApiResponse
        {
            StatusCode = 200,
            Message = "Success",
            Timestamp = DateTime.UtcNow
        };

        // Zero-allocation serialization (source generator optimized)
        var toon = ToonSerializer.Serialize(response);
        return Content(toon, "application/toon");
    }
}

Example 2: Gaming/Real-Time Systems

using ToonNet.Core.Serialization;
using ToonNet.Core.Serialization.Attributes;

[ToonSerializable]
public partial class PlayerState
{
    public int PlayerId { get; set; }
    public Vector3 Position { get; set; }
    public float Health { get; set; }
    public int Score { get; set; }
}

public class NetworkManager
{
    public void BroadcastState(PlayerState state)
    {
        // Critical path - zero allocations
        string data = ToonSerializer.Serialize(state);
        networkSocket.Send(data);
    }

    public PlayerState ReceiveState(string data)
    {
        // Fast deserialization
        return ToonSerializer.Deserialize<PlayerState>(data);
    }
}

Example 3: IoT/Embedded Systems

using ToonNet.Core.Serialization;
using ToonNet.Core.Serialization.Attributes;

[ToonSerializable]
public partial class SensorReading
{
    public DateTime Timestamp { get; set; }
    public double Temperature { get; set; }
    public double Humidity { get; set; }
    public int BatteryLevel { get; set; }
}

public class SensorDevice
{
    public void SendTelemetry()
    {
        var reading = new SensorReading
        {
            Timestamp = DateTime.UtcNow,
            Temperature = ReadTemperature(),
            Humidity = ReadHumidity(),
            BatteryLevel = GetBatteryLevel()
        };

        // Minimal memory footprint
        var payload = ToonSerializer.Serialize(reading);
        mqttClient.Publish("sensors/data", payload);
    }
}

Example 4: Native AOT Application

// Project file configuration
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <PublishAot>true</PublishAot>  
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="ToonNet.Core" />
    <PackageReference Include="ToonNet.SourceGenerators" />
  </ItemGroup>
</Project>

// Code
using ToonNet.Core.Serialization;
using ToonNet.Core.Serialization.Attributes;

[ToonSerializable]
public partial class Config
{
    public string AppName { get; set; }
    public int MaxConnections { get; set; }
}

// Works with Native AOT (no reflection!)
var config = new Config { AppName = "MyApp", MaxConnections = 100 };
var toon = ToonSerializer.Serialize(config);

๐Ÿ” Supported Types

Primitive Types

  • string, int, long, short, byte, sbyte
  • uint, ulong, ushort
  • float, double, decimal
  • bool, char, Guid, DateTime, DateTimeOffset

Collections

  • List<T>, T[]
  • Dictionary<TKey, TValue>
  • IEnumerable<T>, IList<T>, ICollection<T>

Complex Types

  • Nested classes with [ToonSerializable]
  • Nullable types (int?, DateTime?)
  • Enums

Limitations

โŒ Not Supported:

  • Abstract/interface types
  • Circular references
  • Types without parameterless constructor
  • Generic types (not instantiated)

๐Ÿ”’ Thread-Safety

  • Generated serializers and ToonSerializer methods are safe to call concurrently across threads.
  • Shared metadata/name caches use ConcurrentDictionary for concurrent access.
  • Cache entries are created on demand and retained for the process lifetime (no eviction).
  • Do not mutate a single ToonSerializerOptions instance concurrently across threads.

๐Ÿงช Testing

# Run source generator tests
cd tests/ToonNet.SourceGenerators.Tests
dotnet test

# Verify generated code
dotnet build --verbosity detailed
# Check obj/Debug/net8.0/generated/ folder

Core:

Extensions:

Web:

Development:


๐Ÿ“š Documentation


๐Ÿ“‹ Requirements

  • .NET 8.0 or later
  • C# 12.0+ (for partial classes)
  • ToonNet.Core

๐Ÿ“„ License

MIT License - See LICENSE file for details.


๐Ÿค Contributing

Contributions welcome! Please read CONTRIBUTING.md first.


Part of the ToonNet serialization library family.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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 was computed.  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
1.4.0 102 2/8/2026
1.3.0 91 2/4/2026
1.2.0 98 2/1/2026
1.1.0 106 1/28/2026
1.0.0 111 1/12/2026

v1.4.0: Updated to support ToonNet.Core 1.4.0 streaming features.