Alternative specification pattern implementation in C#

Alexander Turtsevitch
3 min readJul 4, 2023

The Specification pattern is not a new thing, but in case your are not familiar with it let’s start with a short recap.

This software design pattern was popularized by Eric Evans in his famous book “Domain-Driven Design” (certainly worth reading). The Specification pattern allows to outline business rule that is combinable with other business rules. The specification object has a clear and limited responsibility, which can be separated and decoupled from the domain object that uses it.

Canonical implementation

Let’s say we have a User and Department entities:

In different places of our code we need to follow the same business rules, for example we might need to check that user is active or he is in a specific department or he has a specific name like “System”. How can we do that?

The lazy way is simply to repeat all that checks in each place where it is needed (violates DRY), that is OK for small and short-lived projects but in most cases it will became a never-ending source of bugs because business rules are complex and tend to change over time and we should not forget to update each usage accordingly. For example, the new requirement could be to also check that user is subscribed.

I should mention that there are ways to solve this problem without using specification pattern:

  • Simply extract expressions to some static field (you can even make it composable with some custom extension methods)
  • Have additional service that checks common business rules (not composable)
  • Create extension methods for IQueryable or IEnumerable (limited composability)

These are valid solutions but still very limited in many ways.

Canonical specification implementation usually looks like this:

You can find more information about this pattern in Wikipedia, on Martin Fowler's site or in other articles on Medium (one, two and many others) or in other sources.

Alternative implementation

We established basic understanding of the problem and solution, but how good our implementation is? The answer is mediocre at best.

Our implementation is too verbose: we have interface with many methods, we have many support classes, we have to extend base class and so on. We use Compile method without caching and it certainly hurts performance.

There is also another distinct problem, see code below for better understanding:

We can not reuse our specifications inside other specifications we can only combine, we got the same problem that we had initially.

These were my reasons for creating a new implementation from scratch.

Personally I came up with the following list of requirements:

  • Single class, no need to extend anything
  • Avoid using extensions methods
  • Avoid useless compilations
  • Provide minimal API
  • Support both expressions and delegates
  • Allow easy declaration
  • Allow easy combination using “&&” , “||” and “!” operators instead of methods
  • Allow to reuse specifications inside other specifications

Yes, there are good existing libraries (namely NSpecifications, LinqSpecs) that are better than everything we had so far but they do not meet all of my requirements.

This is the interface that I came up with (implementation details omitted):

Internally I heavily used Expression APIs and wonderful library DelegateDecompiler which allows to convert delegates back to expressions.

Let’s see how this new implementation can be used:

You can see how easier it is to use and how clean and readable it is, I call it a day.

The code is available on Github, also I created a Nuget package, so you can start experimenting now. Any feedback is appreciated.

--

--