omy.Utils.IO.Serialization.Generators 2.0.0-rc.1

This is a prerelease version of omy.Utils.IO.Serialization.Generators.
dotnet add package omy.Utils.IO.Serialization.Generators --version 2.0.0-rc.1
                    
NuGet\Install-Package omy.Utils.IO.Serialization.Generators -Version 2.0.0-rc.1
                    
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="omy.Utils.IO.Serialization.Generators" Version="2.0.0-rc.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="omy.Utils.IO.Serialization.Generators" Version="2.0.0-rc.1" />
                    
Directory.Packages.props
<PackageReference Include="omy.Utils.IO.Serialization.Generators" />
                    
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 omy.Utils.IO.Serialization.Generators --version 2.0.0-rc.1
                    
#r "nuget: omy.Utils.IO.Serialization.Generators, 2.0.0-rc.1"
                    
#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 omy.Utils.IO.Serialization.Generators@2.0.0-rc.1
                    
#: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=omy.Utils.IO.Serialization.Generators&version=2.0.0-rc.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=omy.Utils.IO.Serialization.Generators&version=2.0.0-rc.1&prerelease
                    
Install as a Cake Tool

omy.Utils.IO.Serialization.Generators

omy.Utils.IO.Serialization.Generators is a Roslyn source generator that produces strongly typed, collision-free reader and writer extension methods for DTOs annotated with [GenerateReaderWriter].

Install

dotnet add package omy.Utils.IO.Serialization.Generators

Supported frameworks

  • netstandard2.0 (analyzer)

Features

  • Discovers classes, structs, and records decorated with [GenerateReaderWriter].
  • Inspects members tagged with [Field(order)] to define binary wire ordering.
  • Emits uniquely named Read<type-identity>_<hash>(this IReader) and Write<type-identity>_<hash>(this IWriter, T value) extension methods.
  • Automatically reuses custom serializers when a member type already exposes matching Read{Member} / Write{Member} extensions.
  • Generates XML-documented, editor-friendly code.

Preparing a model

Annotate each serializable field or property with [Field(order)]. The generator processes members in ascending order:

using Utils.IO.Serialization;

[GenerateReaderWriter]
public partial class InventoryEntry
{
    [Field(0)]
    public required int Id { get; set; }

    [Field(1)]
    public required string Name { get; set; }

    [Field(2)]
    public PriceTag Price { get; set; } = new();
}

[GenerateReaderWriter]
public partial class PriceTag
{
    [Field(0)]
    public decimal Amount { get; set; }

    [Field(1)]
    public string Currency { get; set; } = "EUR";
}

Usage example

using System.IO;
using Utils.IO.Serialization;

var buffer = new MemoryStream();
var writer = new Writer(buffer);
var entry  = new InventoryEntry { Id = 7, Name = "Sprocket", Price = new PriceTag { Amount = 19.95m, Currency = "USD" } };
writer.WriteInventoryEntry_db945a29(entry);

buffer.Position = 0;
var reader       = new Reader(buffer);
InventoryEntry   roundTrip = reader.ReadInventoryEntry_db945a29();

Writer and Reader are the concrete IWriter/IReader implementations from omy.Utils.IO.

Additional scenarios

Nested models

When a member type is also annotated with [GenerateReaderWriter], the generator nests calls to the generated serializer automatically:

[GenerateReaderWriter]
public partial class Shipment
{
    [Field(0)]
    public required int TrackingId { get; set; }

    [Field(1)]
    public required InventoryEntry Item { get; set; }
}

WriteShipment_126422e3 calls WriteInventoryEntry_db945a29 internally; ReadShipment_126422e3 calls ReadInventoryEntry_db945a29.

Reusing manual serializers

If a member type already exposes hand-written Write{Member} / Read{Member} extensions, the generator defers to them:

using Utils.IO.Serialization;

public static class MoneySerializer
{
    public static void WritePriceTag(this IWriter writer, PriceTag value)
    {
        writer.Write<decimal>(value.Amount);
        writer.Write<string>(value.Currency);
    }

    public static PriceTag ReadPriceTag(this IReader reader)
        => new() { Amount = reader.Read<decimal>(), Currency = reader.Read<string>() };
}

[GenerateReaderWriter]
public partial class Invoice
{
    [Field(0)]
    public required int Number { get; set; }

    [Field(1)]
    public required PriceTag Total { get; set; }
}

Because WritePriceTag already exists, the generated WriteInvoice calls it instead of emitting a generic Write<PriceTag>.

Streaming large collections

Generated extensions are regular methods that work with any Stream-backed Writer/Reader:

using System.IO;
using Utils.IO.Serialization;

await using var stream = File.OpenWrite("report.bin");
var writer = new Writer(stream);

foreach (InventoryEntry item in inventory)
    writer.WriteInventoryEntry_db945a29(item);
  • omy.Utils.IO – provides IReader, IWriter, Reader, Writer, [GenerateReaderWriter], and [Field].
  • omy.Utils – shared helpers.

Versioned API documentation

Version 2 generated method names

Version 2 uses the complete metadata identity for every generated class, hint name, reader, and writer. A method follows Read<sanitized-full-identity>_<stable-hash> / Write<sanitized-full-identity>_<stable-hash> rather than Read<TypeName> / Write<TypeName>. The readable prefix contains the namespace and containing types; the deterministic FNV-1a suffix prevents the remaining escaped-name collisions. This is an intentional 2.0 source-breaking change—use the generated member offered by IntelliSense rather than hard-coding a simple-name convention.

Contracts containing init-only properties are rejected with UIOSG010; the generator emits no source for that type, so consumer compilations do not receive a secondary assignment error from a .g.cs file.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

  • .NETStandard 2.0

    • No dependencies.

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
2.0.0-rc.1 153 8/28/2026
1.2.1 478 11/3/2025