ZeroAlloc.Specification.Generator
1.0.1
dotnet add package ZeroAlloc.Specification.Generator --version 1.0.1
NuGet\Install-Package ZeroAlloc.Specification.Generator -Version 1.0.1
<PackageReference Include="ZeroAlloc.Specification.Generator" Version="1.0.1"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="ZeroAlloc.Specification.Generator" Version="1.0.1" />
<PackageReference Include="ZeroAlloc.Specification.Generator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add ZeroAlloc.Specification.Generator --version 1.0.1
#r "nuget: ZeroAlloc.Specification.Generator, 1.0.1"
#:package ZeroAlloc.Specification.Generator@1.0.1
#addin nuget:?package=ZeroAlloc.Specification.Generator&version=1.0.1
#tool nuget:?package=ZeroAlloc.Specification.Generator&version=1.0.1
ZeroAlloc.Specification
Source-generated, zero-allocation specification pattern for .NET 8+.
Multiple packages in this family — see Documentation or NuGet for the full list.
Install
The source generator is bundled into the main package — a single PackageReference is all you need:
dotnet add package ZeroAlloc.Specification
The standalone
ZeroAlloc.Specification.Generatorpackage is still published for backwards compatibility with existing direct PackageReferences, but new consumers should reference onlyZeroAlloc.Specification.
Example
[Specification]
public readonly partial struct ActiveUserSpec : ISpecification<User>
{
public bool IsSatisfiedBy(User user) => user.IsActive;
public Expression<Func<User, bool>> ToExpression() => u => u.IsActive;
}
[Specification]
public readonly partial struct PremiumUserSpec : ISpecification<User>
{
private readonly decimal _minSpend;
public PremiumUserSpec(decimal minSpend) => _minSpend = minSpend;
public bool IsSatisfiedBy(User user) => user.TotalSpend >= _minSpend;
public Expression<Func<User, bool>> ToExpression()
{
var min = _minSpend;
return u => u.TotalSpend >= min;
}
}
// Fluent composition — zero allocation
var spec = new ActiveUserSpec().And(new PremiumUserSpec(1000m));
// In-memory
bool result = spec.IsSatisfiedBy(user);
// EF Core — translates to SQL
var users = await dbContext.Users.Where(spec.ToExpression()).ToListAsync();
Features
- Zero allocations — composed specs are
readonly structvalues, not heap objects - EF Core compatible — every spec exposes
ToExpression()returningExpression<Func<T, bool>> - Source-generated fluent API —
And<TOther>(),Or<TOther>(),Not()added by Roslyn generator - Static builder —
Spec.And(),Spec.Or(),Spec.Not()for explicit type arguments - Compile-time safety — ZA001–ZA004 diagnostics enforce correct
partial structusage - .NET 8+, C# 12
Documentation
| Page | Description |
|---|---|
| Introduction | What it is and why it exists |
| Getting Started | Install and first specification in 5 minutes |
| Core Concepts | ISpecification<T>, structs, stateful vs stateless |
| Fluent API | Generated And/Or/Not methods |
| Static Builder | Spec.And/Or/Not |
| Expression Composition | ToExpression() and EF Core translation |
| Diagnostics | ZA001–ZA004 compile-time errors and fixes |
| Generator Internals | How the Roslyn generator works |
| Performance | Allocation comparison and benchmarks |
| Cookbook: EF Core Repository | Repository pattern integration |
| Cookbook: Combining Specs | Complex compositions |
| Cookbook: Stateless Caching | Cache expression trees for stateless specs |
License
MIT — see LICENSE.
Learn more about Target Frameworks and .NET Standard.
This package has 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.