PureSpec 0.0.1-alpha-7

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

PureSpec

Build and Test NuGet .NET 10 License

PureSpec is a minimalist implementation of the Specification pattern for creating reusable business rules.

Features

  • Expression-based specifications.
  • Rule composition with And, Or, AndNot, OrNot, and Not.
  • Rule checks.
  • Reusable projections.
  • Expressions compatible with LINQ and Entity Framework Core.

Getting Started

Installation

dotnet add package PureSpec --version 0.0.1-alpha-7

Create a rule from an expression:

using PureSpec;

var publishedSpec = new Specification<Book>(book => book.IsPublished);
var scienceFictionSpec = new Specification<Book>(book => book.Genre == "Science fiction");
var newSpec = new Specification<Book>(book => book.PublishedAt > DateTime.UtcNow.AddDays(-7));

// You can combine rules
var featuredSpec = publishedSpec
    .And(newSpec);

var featuredBook = new Book("Dune", "Science fiction", true, DateTime.UtcNow.AddDays(-1));
var oldBook = new Book("Harry Potter", "Fantasy", true, DateTime.UtcNow.AddDays(-10));

// true
Console.WriteLine(featuredSpec.IsSatisfiedBy(featuredBook));

// false (old)
Console.WriteLine(featuredSpec.IsSatisfiedBy(oldBook));

// true
Console.WriteLine(scienceFictionSpec.IsSatisfiedBy(featuredBook));

// false (genre Fantasy)
Console.WriteLine(scienceFictionSpec.IsSatisfiedBy(oldBook));

// true (genre is not Science fiction)
Console.WriteLine(scienceFictionSpec.Not().IsSatisfiedBy(oldBook));

public sealed record Book(string Title, string Genre, bool IsPublished, DateTime PublishedAt);

Create specification type for reuse:

using PureSpec;

var deletedAuthor = new Author("Clara Jennings", true);
var availableAuthor = new Author("Thomas McRae", false);

var books = new List<Book>
{
    new Book("The Vanishing Hour", true, deletedAuthor),
    new Book("Ashes Beneath", false, deletedAuthor),
    new Book("Dead Man's Loop", true, availableAuthor),
    new Book("Code Silence", false, availableAuthor)
};

var bookIsAvailableSpec = new BookIsAvailableSpec();

var availableBooks = books.Where(bookIsAvailableSpec.ToFunc()).ToList();

// Only "Dead Man's Loop" is published and has an author who is not deleted.
foreach (var availableBook in availableBooks)
{
    Console.WriteLine(availableBook.Title);
}

public class BookIsAvailableSpec() :
    Specification<Book>(book =>
        book.IsPublished &&
        !book.Author.IsDeleted);

public sealed record Book(string Title, bool IsPublished, Author Author);

public sealed record Author(string Name, bool IsDeleted);

Project a specification:

var projection = bookIsAvailableSpec.Project<BookDto>(
    book => new BookDto(book.Title));

var dto = projection.CompileSelector()(books[2]);

public sealed record BookDto(string Title);

or

var projection = new SpecificationProjection<Book, BookDto>(
    bookIsAvailableSpec,
    book => new BookDto(book.Title));

public sealed record BookDto(string Title);

or

var projection = new BookProjection();

public class BookProjection() :
    SpecificationProjection<Book, BookDto>(
        new BookIsAvailableSpec(),
        book => new BookDto(book.Title));

public sealed record BookDto(string Title);

A specification projection exposes both Predicate and Selector expressions. Use CompilePredicate and CompileSelector for in-memory evaluation, or pass the expressions directly to LINQ providers.

LINQ queries

Use Predicate with IQueryable<TEntity> and compose sorting and paging with standard LINQ operators:

var specification = new BookIsAvailableSpec();

var books = await dbContext.Books
    .AsNoTracking()
    .Where(specification.Predicate)
    .OrderBy(book => book.Title)
    .Skip(10)
    .Take(20)
    .ToArrayAsync(cancellationToken);

The expression remains available to the query provider, so Entity Framework Core can translate it to SQL. For in-memory collections, use ToFunc() or compile the predicate:

var books = allBooks.Where(specification.ToFunc()).ToArray();

Apply a specification projection by using both expressions:

var specification = new BookIsAvailableSpec().Project(
    book => new BookDto(book.Title));

var books = await dbContext.Books
    .AsNoTracking()
    .Where(specification.Predicate)
    .Select(specification.Selector)
    .ToArrayAsync(cancellationToken);

PureSpec does not provide repository, persistence, or transaction abstractions. Use the data access API appropriate for your application for writes and transaction management.

License

MIT

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 (1)

Showing the top 1 NuGet packages that depend on PureSpec:

Package Downloads
RepoStack.PureSpecExtension

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.0.1-alpha-7 87 8/30/2026

0.0.1-alpha-7