Beskar.CodeGeneration.TypeIdGenerator
1.0.6
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
<PackageReference Include="Beskar.CodeGeneration.TypeIdGenerator" Version="1.0.6" />
<PackageVersion Include="Beskar.CodeGeneration.TypeIdGenerator" Version="1.0.6" />
<PackageReference Include="Beskar.CodeGeneration.TypeIdGenerator" />
paket add Beskar.CodeGeneration.TypeIdGenerator --version 1.0.6
#r "nuget: Beskar.CodeGeneration.TypeIdGenerator, 1.0.6"
#:package Beskar.CodeGeneration.TypeIdGenerator@1.0.6
#addin nuget:?package=Beskar.CodeGeneration.TypeIdGenerator&version=1.0.6
#tool nuget:?package=Beskar.CodeGeneration.TypeIdGenerator&version=1.0.6
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 asreadonly record structsfor 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>andISpanFormattable, 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 | Versions 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. |
-
net10.0
- Beskar.CodeGeneration.TypeIdGenerator.Marker (>= 1.0.6)
- Me.Memory (>= 1.3.7)
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 |