Beskar.CodeGeneration.TypeIdGenerator 1.0.6

There is a newer version of this package available.
See the version list below for details.
dotnet add package Beskar.CodeGeneration.TypeIdGenerator --version 1.0.6
                    
NuGet\Install-Package Beskar.CodeGeneration.TypeIdGenerator -Version 1.0.6
                    
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="Beskar.CodeGeneration.TypeIdGenerator" Version="1.0.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Beskar.CodeGeneration.TypeIdGenerator" Version="1.0.6" />
                    
Directory.Packages.props
<PackageReference Include="Beskar.CodeGeneration.TypeIdGenerator" />
                    
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 Beskar.CodeGeneration.TypeIdGenerator --version 1.0.6
                    
#r "nuget: Beskar.CodeGeneration.TypeIdGenerator, 1.0.6"
                    
#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 Beskar.CodeGeneration.TypeIdGenerator@1.0.6
                    
#: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=Beskar.CodeGeneration.TypeIdGenerator&version=1.0.6
                    
Install as a Cake Addin
#tool nuget:?package=Beskar.CodeGeneration.TypeIdGenerator&version=1.0.6
                    
Install as a Cake Tool

Beskar.CodeGeneration.TypeIdGenerator

A high-performance C# Source Generator designed to create implementation-heavy, type-safe identifiers (Strongly Typed IDs) for .NET 10 and higher. By decorating a simple readonly partial record struct with the [TypeSafeId] attribute, the generator produces a robust implementation including conversions, parsing logic, and interface implementations.

Features

  • 📦 Compact Storage: Generated IDs are based on unmanaged types (e.g., int, long, Guid) and stored as readonly record structs for zero-allocation overhead.
  • 🔄 Comprehensive Conversions: Automatically generates implicit and explicit conversion operators between the ID and its underlying value, including nullable support.
  • 🔡 Text & Span Support: Implements ISpanParsable<T> and ISpanFormattable, allowing efficient parsing and formatting without string allocations.
  • 🔍 Domain Integrity: Implements ITypeSafeIdentifier<T>, providing a unified interface for ID comparison and value access across your domain.
  • 🛠️ Customizable Generation: Fine-tune the generated output (e.g., toggle JSON converters, string overrides, or conversion types) via attribute properties.

Getting Started

using Beskar.CodeGeneration.TypeIdGenerator.Marker.Attributes;

namespace MyProject.Domain;

[TypeSafeId]
public readonly partial record struct ExampleId(long Value);

Will generate something along the lines of:

[StructLayout(LayoutKind.Sequential)]
[DebuggerDisplay("{DebuggerView,nq}")]
internal readonly partial record struct ExampleId(long Value)
   : IComparable<ExampleNumberId>, ISpanParsable<ExampleNumberId>, ITypeSafeIdentifier<long>, ISpanFormattable
{
   // Static constant like fields
   public static ExampleNumberId Empty { get; } = new (0); 
   public static ExampleNumberId MaxValue { get; } = new (long.MaxValue); 

   // Check properties
   public bool IsEmpty => Value == 0;
   public bool IsMaxValue => Value == long.MaxValue;
   public bool HasValue => !IsEmpty;
   
   // Stringify and debugger view
   public override string ToString() => $"{nameof(ExampleNumberId)}: {Value}";
   internal string DebuggerView => ToString();
   
   public bool Equals(ExampleNumberId other)
   {
      return Value == other.Value;
   }
   
   public override int GetHashCode()
   {
      return Value.GetHashCode();
   }
   
   // Comparable interface
   public int CompareTo(ExampleNumberId other) => Value.CompareTo(other.Value);
   
   // Compare operators
   public static bool operator <(ExampleNumberId left, ExampleNumberId right) => left.Value < right.Value; 
   public static bool operator <=(ExampleNumberId left, ExampleNumberId right) => left.Value <= right.Value; 
   public static bool operator >(ExampleNumberId left, ExampleNumberId right) => left.Value > right.Value; 
   public static bool operator >=(ExampleNumberId left, ExampleNumberId right) => left.Value >= right.Value; 
   
   // Implicit non-nullable conversions
   public static implicit operator long(ExampleNumberId id) => id.Value;
   public static implicit operator ExampleNumberId(long value) => new(value);
   
   // Implicit nullable conversions
   public static implicit operator long?(ExampleNumberId? id) => id?.Value;
   public static implicit operator ExampleNumberId?(long? value) => value.HasValue ? new ExampleNumberId(value.Value) : null;
   
   // Implicit non-nullable to nullable conversions
   public static implicit operator long?(ExampleNumberId id) => id.Value;
   public static implicit operator ExampleNumberId?(long value) => new ExampleNumberId(value);
   
   // Explicit nullable to non-nullable conversions
   public static explicit operator long(ExampleNumberId? id) => id ?? Empty;
   public static explicit operator ExampleNumberId(long? value) => value.HasValue ? new ExampleNumberId(value.Value) : Empty;
   
   // Span parsable interface
   public static ExampleNumberId Parse(string s, IFormatProvider? provider)
      => Parse(s.AsSpan(), provider);

   public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out ExampleNumberId result)
      => TryParse(s.AsSpan(), provider, out result);

   public static ExampleNumberId Parse(ReadOnlySpan<char> s, IFormatProvider? provider)
   {
      return new ExampleNumberId(long.Parse(s, provider));
   }

   public static bool TryParse(ReadOnlySpan<char> s, IFormatProvider? provider, out ExampleNumberId result)
   {
      if (long.TryParse(s, provider, out var value))
      {
         result = new ExampleNumberId(value);
         return true;
      }
      
      result = default;
      return false;
   }
   
   // Type safe identifier interface
   public int CompareTo(ITypeSafeIdentifier<long>? other)
   {
      return other switch 
      { 
         null => 1, 
         ExampleNumberId id => Value.CompareTo(id.Value), 
         _ => throw new ArgumentException($"Object must be of type ExampleNumberId.") 
      }; 
   }
   
   public bool Equals(ITypeSafeIdentifier<long>? other)
   {
      return other is ExampleNumberId id && Value == id.Value;
   }
   
   // Span formattable
   public string ToString(string? format, IFormatProvider? formatProvider)
      => Value.ToString(format, formatProvider);

   public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider)
      => Value.TryFormat(destination, out charsWritten, format, provider);
}
Product Compatible and additional computed target framework versions.
.NET 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 (2)

Showing the top 2 NuGet packages that depend on Beskar.CodeGeneration.TypeIdGenerator:

Package Downloads
Beskar.CodeGeneration.ContentGenerator.Marker

Generate headless cms like structures for ef core.

Beskar.CodeGeneration.ContentGenerator

Generate headless cms like structures for ef core.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.1 96 4/29/2026
1.2.0 128 4/26/2026
1.1.9 111 4/25/2026
1.1.8 91 4/8/2026
1.1.7 86 4/7/2026
1.1.6 101 4/5/2026
1.1.5 87 4/5/2026
1.1.4 101 4/4/2026
1.1.3 91 4/4/2026
1.1.2 100 4/2/2026
1.1.1 101 4/2/2026
1.0.9 101 4/2/2026
1.0.8 92 4/1/2026
1.0.7 91 4/1/2026
1.0.6 88 4/1/2026
1.0.5 91 4/1/2026
1.0.4 95 4/1/2026
1.0.3 89 4/1/2026
1.0.2 95 4/1/2026
1.0.1 90 4/1/2026
Loading failed