Class Specification<T>
- Namespace
- Trellis
- Assembly
- Trellis.DomainDrivenDesign.dll
Base class for the Specification pattern. Encapsulates a business rule as a composable, storage-agnostic expression tree.
public abstract class Specification<T>
Type Parameters
TThe type of entity this specification applies to.
- Inheritance
-
Specification<T>
- Inherited Members
- Extension Methods
Examples
Define a specification:
public class OverdueOrderSpec(DateTimeOffset now) : Specification<Order>
{
public override Expression<Func<Order, bool>> ToExpression() =>
order => order.Status == OrderStatus.Submitted
&& order.SubmittedAt < now.AddDays(-30);
}
Compose specifications:
var spec = new OverdueOrderSpec(now).And(new HighValueOrderSpec(500m));
var orders = await repository.ListAsync(spec, ct);
In-memory evaluation:
if (spec.IsSatisfiedBy(order))
// order matches the specification
Remarks
The Specification pattern enables:
- Encapsulating business rules as reusable, named objects
- Composing complex rules from simple ones using And(Specification<T>), Or(Specification<T>), and Not()
- Passing specifications to repositories for server-side filtering via expression trees
- In-memory evaluation via IsSatisfiedBy(T)
Specifications are storage-agnostic domain concepts. They produce expression trees
that LINQ providers (such as EF Core 8+) can translate to SQL. Repository interfaces
accept Specification<T> and the ACL layer applies them to queries.
Constructors
Specification()
Initializes a new instance of the Specification<T> class, setting up lazy compilation caching for IsSatisfiedBy(T).
protected Specification()
Properties
CacheCompilation
Gets a value indicating whether the compiled expression should be cached.
Override and return false to force recompilation on each
IsSatisfiedBy(T) call (e.g., when the expression changes between invocations).
protected virtual bool CacheCompilation { get; }
Property Value
Methods
And(Specification<T>)
Combines this specification with another using logical AND.
public Specification<T> And(Specification<T> other)
Parameters
otherSpecification<T>The specification to combine with.
Returns
- Specification<T>
A new specification that is satisfied only when both specifications are satisfied.
IsSatisfiedBy(T)
Evaluates this specification against an in-memory instance.
public bool IsSatisfiedBy(T entity)
Parameters
entityTThe entity to evaluate against this specification.
Returns
- bool
trueif the entity satisfies this specification; otherwise,false.
Not()
Negates this specification.
public Specification<T> Not()
Returns
- Specification<T>
A new specification that is satisfied when this specification is not satisfied.
Or(Specification<T>)
Combines this specification with another using logical OR.
public Specification<T> Or(Specification<T> other)
Parameters
otherSpecification<T>The specification to combine with.
Returns
- Specification<T>
A new specification that is satisfied when either specification is satisfied.
ToExpression()
The expression tree representing this specification's business rule. Consumers (repositories, LINQ providers) use this to filter data.
public abstract Expression<Func<T, bool>> ToExpression()
Returns
- Expression<Func<T, bool>>
An expression tree that can be compiled for in-memory evaluation or translated by a LINQ provider for server-side filtering.
Operators
implicit operator Expression<Func<T, bool>>(Specification<T>)
Implicit conversion to Expression<TDelegate> for seamless LINQ integration.
Enables: query.Where(spec) without calling ToExpression().
public static implicit operator Expression<Func<T, bool>>(Specification<T> spec)
Parameters
specSpecification<T>The specification to convert.
Returns
- Expression<Func<T, bool>>
The expression tree representing this specification's business rule.