Skip to content

Raffinert/Raffinert.Spec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

65 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Stand With Ukraine

Raffinert.Spec

NuGet version (Raffinert.Spec)

Raffinert.Spec

Raffinert.Spec is a rethinking of libraries and sources such as:

Why Another Specification Library?

The main goal was to create a simple replacement of LINQKit library without any Entity Framework specific tweaks (see the LINQKit vs Spec Comparison and discussion about embedding linqKit into EfCore). Please treat the specification as an expression constructor.

With Raffinert.Spec you can:

  • Combine expressions with logical operators OR, AND, NOT.
  • Use nested specifications by calling IsSatisfiedBy method.
  • Create specification templates and apply them to different entities with similar signatures.

Usage

Detailed examples can be found in Integration Tests

Defining a Specification

You can define specifications either inline or create custom specification classes. Below is an example of a custom specification for filtering products by name:

using Raffinert.Spec;
using System.Linq.Expressions;

public class ProductNameSpec : Spec<Product>
{
    private readonly string _name;

    public ProductNameSpec(string name)
    {
        _name = name;
    }

    public override Expression<Func<Product, bool>> GetExpression()
    {
        return product => product.Name == _name;
    }
}

Specification Templates

Specification templates allow you to define reusable structures that can be adapted to different entities with similar properties.

Example: Creating and Adapting a Specification Template

var template = SpecTemplate<Product>.Create(p => new { p.Name, p.Price }, t => t.Name == "Banana" && t.Price > 10);
var adaptedSpec = template.Adapt<InventoryItem>();

In this example, a specification template is created for Product, filtering based on Name and Price. The template is then adapted to an InventoryItem type with matching properties.

Roslyn Analyzers for Compile-Time Validation

To prevent runtime errors when using SpecTemplate, we provide Roslyn Raffinert.Spec.Analyzer that:

  • Ensure SpecTemplate<TSample>.Adapt<TN>() only adapts to types that contain all required members.
  • Validate that SpecTemplate.Create(...) uses either an anonymous type projection (e.g., p => new { p.Name }) or class initialize statement (e.g., p => new Template{ Name = p.Name }).

These analyzers catch issues at compile-time, improving reliability and maintainability.

Debugging

The Spec<T> class includes built-in debugging support with a custom debugger display, giving developers an immediate view of the underlying expression while debugging.

See also Raffinert.Proj library.

About

A lightweight, composable specification library designed for building reusable query logic, with a focus on Entity Framework.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages