DanMarshall.FluentSpecifications 1.1.0

dotnet add package DanMarshall.FluentSpecifications --version 1.1.0
                    
NuGet\Install-Package DanMarshall.FluentSpecifications -Version 1.1.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="DanMarshall.FluentSpecifications" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DanMarshall.FluentSpecifications" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="DanMarshall.FluentSpecifications" />
                    
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 DanMarshall.FluentSpecifications --version 1.1.0
                    
#r "nuget: DanMarshall.FluentSpecifications, 1.1.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 DanMarshall.FluentSpecifications@1.1.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=DanMarshall.FluentSpecifications&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=DanMarshall.FluentSpecifications&version=1.1.0
                    
Install as a Cake Tool

Fluent Specifications

Specifications for modern C#.

Fluent Specifications is a C# 14 implementation of the Specification Pattern designed around terse domain language, structured explanations, and repository boundaries that do not leak IQueryable.

Read the polished documentation at fluent-specifications.danmarshall.dev.

Install

dotnet add package DanMarshall.FluentSpecifications

One package installs the Spec<T> and provider-neutral search runtime plus the source generator that produces fluent rules plus opt-in fields, search phrases, and domain properties such as order.CanShip.

Zero third-party package dependencies

The package has zero third-party package dependencies. Its NuGet dependency list is empty: the runtime uses the .NET platform, and the generator uses the Roslyn compiler APIs supplied by Microsoft's C# toolchain. It neither downloads nor bundles another vendor's runtime or compiler assemblies.

Readable at the call site

The primary search example is fully generated from the entity's rule and field catalogs—without a lambda, string field name, operator overload, DbSet, or IQueryable:

var request = Order.Search
    .Matching.CanShip.And.HighPriority
    .Sorted.By.CreatedAt.Desc
    .Then.By.Id.Asc
    .Page(2).OfSize(50);

The example application composes an immutable rule without overloaded Boolean operators:

public static Spec<Order> ReadyToShip() =>
    CanShip.And.HighPriority.AndNot.Suspended;

Important argument-free rules can become opt-in domain properties:

public static bool ShouldDispatch(Order order)
{
    if (order.CanShip)
    {
        return true;
    }

    return false;
}

Routine application code does not need IsSatisfiedBy, Satisfies, expression plumbing, or a query provider.

One named rule tree

Catalog rules retain stable identity, metadata, and their underlying Boolean structure:

[Expose]
public static Spec<Order> CanShip =>
    Paid
        .And(HasDeliveryAddress)
        .AndNot(Suspended)
        .Named(
            "order.can-ship",
            "Can ship",
            "The order is not ready to ship.");

The same Spec<T> supports short-circuiting in-memory evaluation, complete or short-circuit diagnostics, safe rendering, provider-neutral traversal, and infrastructure translation.

Persistence stays behind the repository

Application repositories accept rules and return materialized answers:

public interface IOrderRepository
{
    Task<IReadOnlyList<Order>> ListAsync(
        Spec<Order> specification,
        CancellationToken cancellationToken = default);

    Task<bool> AnyAsync(
        Spec<Order> specification,
        CancellationToken cancellationToken = default);

    Task<Page<Order>> FindAsync(
        PagedSearch<Order> search,
        CancellationToken cancellationToken = default);
}

The optional relational EF Core adapter preflights translation and materializes List, Page, Any, or Count operations. Unsupported filters or sorts produce structured translation errors before a SELECT; they never trigger implicit client-side filtering. Its public API does not accept or return IQueryable.

Read the EF Core guide for null semantics, collations, navigations, global filters, provider limitations, and the limits of SQLite-based testing.

Projects

  • FluentSpecifications.Core — immutable rule tree, evaluation, diagnostics, traversal, and translation contracts.
  • FluentSpecifications.Generators — C# 14 connector and domain extension properties plus compile-time diagnostics.
  • FluentSpecifications.Expressions — parameter-rebound expression plans without InvocationExpression.
  • FluentSpecifications.EntityFrameworkCore — relational translation preflight and materializing operations for infrastructure.
  • OrderFulfilment — the executable domain example used throughout the tests and documentation.
  • FluentSpecifications.Docs — Roslyn-based extraction of real source symbols into Markdown and the Astro landing page.

Prior art and acknowledgements

Fluent Specifications is informed by the original Specification pattern and by practical lessons from several libraries and policy systems:

  • Ardalis.Specification, created by Steve Smith, demonstrated reusable named specifications and small repository surfaces;
  • Spring Data JPA Specifications keeps criteria separate from repository execution;
  • RulerZ demonstrates a provider-neutral rule model compiled for different targets;
  • Happyr Doctrine Specification illustrates both repository-owned application and the tension created when Boolean rules also carry query modifiers;
  • Konform, NSpecifications, and spec-pattern informed structured results, expression composition, and explicit composite trees;
  • Cedar and Open Policy Agent informed stable rule identity, explicit errors, preparation, and traceability; and
  • an internal Kotlin implementation Dan used while working at Reapit showed how much terse, fluent domain language matters at ordinary call sites.

These are influences, not compatibility targets. Fluent Specifications keeps a deliberately narrower Boolean core and does not copy their APIs.

Documentation that cannot drift quietly

Every fenced C# sample in the documentation carries a canonical Roslyn documentation ID in its fence metadata. npm run snippets:sync resolves those symbols—including overload signatures—and regenerates the fence bodies from the repository. Missing, ambiguous, or stale extracts fail npm run snippets:check.

The documentation site is authored as Markdown under src/content/docs, built with Astro into docs/, and published by GitHub Actions under gh-pages:/docs. Both CNAME copies target fluent-specifications.danmarshall.dev, matching the deployment style used by Dan's blog.

Build and test

Restore with dotnet restore FluentSpecifications.slnx and npm ci.

Run the complete .NET suite with dotnet test FluentSpecifications.slnx --configuration Release --no-restore -m:1 -nr:false. Run npm test to verify snippet freshness, Markdown contracts, the production Astro build, metadata, custom-domain artifacts, and internal links.

DanMarshall.FluentSpecifications 1.x is the public starter package. Releases begin at 1.0.0. The next release is selected manually with the Core project's Version; CI reads its exact effective PackageVersion rather than deriving a version from Git history. The publisher checks the selected version against NuGet.org before packing or requesting credentials. It accepts only the immediate next patch, minor, or major SemVer transition, so an unchanged version, duplicate, or gap fails before Trusted Publishing authentication. The checked-in SPECIFICATION.md, package-consumer tests, and executable conformance suites define its version-one contract.

NuGet releases use Trusted Publishing. GitHub exchanges a short-lived OIDC identity for a temporary NuGet.org credential immediately before publication; the repository stores no long-lived publishing API key.

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.
  • net10.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
1.1.0 105 8/31/2026
1.0.0 137 8/31/2026

Adds opt-in, provider-neutral search shaping with generated rule and field catalogs, ordering, paging, and relational EF Core execution contracts.