Specification Pattern Implementation

By Dries Marckmann
November 30, 2010
0

For some time now I’ve been willing to find a good implementation of the Specification Pattern. Information about this pattern can be found here:

http://en.wikipedia.org/wiki/Specification_pattern

interface ISpecification<TEntity>
{
	bool IsSatisfiedBy(TEntity item);
}

The idea I had was to use the IQueryable of Linq to query over large collections of objects and get all the benefits of delayed execution.

Recently I came across a blog post by Dennis Doomen who  did exactly that. Read about it here:

http://www.dennisdoomen.net/2010/10/my-silverlight-4-reference-architecture_12.html

That implementation gives me:

public class ActiveRegistrationsSpecification
{
	public IQueryable<Registration> SatisfyingElementsFrom
	(IQueryable<registration> registrations)
	{
		return registrations
			.Where(r => r.Status != AgreementStatus.Incomplete);
	}
}

What I ultimately wanted was an implementation that has both capabilities, to evaluate a single item and to get all items from a collection.

Today I found a very old blog post of Nicholas Blumhardt that did that:

http://nblumhardt.com/archives/implementing-the-specification-pattern-via-linq/

public abstract class Specification<T>
{
	public bool IsSatisfiedBy(T item)
	{
		return SatisfyingElementsFrom(new[] { item }.AsQueryable()).Any();
	}

	public abstract IQueryable<T> SatisfyingElementsFrom
	(IQueryable<T> candidates);
}

However this implementation has a downside as Nicholas Blumhardt already states:

“Unknown performance ramifications of AsQueryable() under heavy usage”

And he is right. The AsQueryable() usage is very slow compared to the normal IsSatisfiedBy method.

My idea to improve this implementation was to make the both methods use a Predicate. Of course this wasn’t all that easy, but after some testing I ended up with this very useful implementation:

 

public abstract class Specification<TEntity>
{
	protected Func<TEntity, bool> evalCompiled;
	protected Expression<Func<TEntity, bool>> evalExpression;

	internal Expression<Func<TEntity, bool>> Predicate
	{
		get
		{
			return evalExpression;
		}
		set
		{
			evalExpression = value;
			evalCompiled = evalExpression.Compile();
		}
	}

	public bool IsSatisfiedBy(TEntity item)
	{
		return evalCompiled(item);
	}

	public IQueryable<TEntity> SatisfyingElementsFrom
	(IQueryable<TEntity> candidates)
	{
		return candidates.Where(evalExpression);
	}
}

Next on my wishlist is to get a CompositeSpecification so I can combine specifications with And and Or or Negate a specification. I will keep you posted.

Comments: 0

Leave a Reply

Your email address will not be published. Required fields are marked *