Skip to content

Instantly share code, notes, and snippets.

@rbwestmoreland
Created December 18, 2011 03:13
Show Gist options
  • Save rbwestmoreland/1492253 to your computer and use it in GitHub Desktop.
Save rbwestmoreland/1492253 to your computer and use it in GitHub Desktop.
Properly Implementing the Specification Pattern
using System;
internal class AndSpecification<T> : ISpecification<T>
{
private ISpecification<T> Specification1 { get; set; }
private ISpecification<T> Specification2 { get; set; }
internal AndSpecification(ISpecification<T> s1, ISpecification<T> s2)
{
Specification1 = s1;
Specification2 = s2;
}
public bool IsSatisfiedBy(T entity)
{
return Specification1.IsSatisfiedBy(entity) && Specification2.IsSatisfiedBy(entity);
}
}
using System;
/// <summary>
/// A generic Specification.
/// <para>The Specification pattern is a behavioral
/// pattern, whose purpose is to provide recombinable
/// business logic in a boolean fashion.</para>
/// </summary>
/// <typeparam name="T">The type which the specification belongs.</typeparam>
public interface ISpecification<T>
{
bool IsSatisfiedBy(T entity);
}
using System;
public static class ISpecificationExtensions
{
public static ISpecification<T> And<T>(this ISpecification<T> s1, ISpecification<T> s2)
{
return new AndSpecification<T>(s1, s2);
}
public static ISpecification<T> Or<T>(this ISpecification<T> s1, ISpecification<T> s2)
{
return new OrSpecification<T>(s1, s2);
}
public static ISpecification<T> Not<T>(this ISpecification<T> s)
{
return new NotSpecification<T>(s);
}
}
using System;
internal class NotSpecification<T> : ISpecification<T>
{
private ISpecification<T> Specification { get; set; }
internal NotSpecification(ISpecification<T> specification)
{
Specification = specification;
}
public bool IsSatisfiedBy(T candidate)
{
return !Specification.IsSatisfiedBy(candidate);
}
}
using System;
internal class OrSpecification<T> : ISpecification<T>
{
private ISpecification<T> Specification1 { get; set; }
private ISpecification<T> Specification2 { get; set; }
internal OrSpecification(ISpecification<T> s1, ISpecification<T> s2)
{
Specification1 = s1;
Specification2 = s2;
}
public bool IsSatisfiedBy(T entity)
{
return Specification1.IsSatisfiedBy(entity) || Specification2.IsSatisfiedBy(entity);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment