E muito comum termos que duplicar partes dos criterios feitos em consultas a banco de dados para atender regras de negocio. O Specification pattern tenta resolver esse problema agrupando esses criterios em classes, e usa uma composicao de specifications para unir todos os criterios. QueryOverSpecification e uma pequena biblioteca implementando uma variacao do padrao para uso com NHibernate QueryOver.Specification PatternBasicamente o padrao e uma interface com um metodo que diz se a entidade satisfaz ou nao um criterio, ou seja, um predicado sobre um objeto.public interface ISpecification{ bool IsSatisfiedBy(object candidate);} public class CourseWithVotes : ISpecification{ public bool IsSatisfiedBy(Course course) { return course.Votes.Count > 0; }}O problema com essa abordagem e que a implementacao pode causar problemas de performance se usado em um base de dados com uma grande quantidade de registros, ja que para cada registro, devera ser feita a chamada do metodo para verificacao se o objeto satisfaz ou nao a Specification.Uma alternativa para .NET e o uso do LINQ, mas para projetos que preferivelmente seja melhor o uso do QueryOver, a biblioteca QueryOverSpecification da o suporte necessario para o reuso das consultas.DomainFazendo esse mesmo exemplo usando QueryOverSpecification, teriamos: public interface ICourseWithVotes { ISpecification<Course> By(); } public class CourseWithVotes : ICourseWithVotes { public ISpecification<Course> By() { Action<IQueryOver<Course, Course>> action = x => x.JoinQueryOver(y => y.Votes); return new QueryOverSpecification<Course>(action); } }Veja que mudamos a forma como a Specification e usada. Criamos um delegate action sobre uma instancia de QueryOver de Course, ou seja, o que eu devo adicionar ao QueryOver para efetuar o criterio sobre o Course. Passamos essa action para a classe QueryOverSpecification, que cria uma specification usando um QueryOver.RepositoryAbaixo segue um exemplo de um metodo Find() generico da classe Repository, que recebe uma ISpecification e retorna a lista de objetos que satisfazem ao criterio: public IList<TEntity> Find<TEntity>(ISpecification<TEntity> spec) where TEntity : class, IIdAccessor { var session = Factory.OpenSession(); var query = session.QueryOver<TEntity>(); var visitor = new QueryOverSpecificationVisitor<TEntity>(query); spec.Accept(visitor); var list = query.List(); session.Close(); return list; }*Esse metodo e somente um exemplo com nenhum tratamento de exception ou transaction. QueryOverSpecificationVisitor e uma classe que recebe um QueryOver e adiciona todos os criterios necessarios para efetuar a consulta, depois e so executar o metodo List() do QueryOver para ter a lista de objetos.ServiceDentro de uma classe Service, teriamos a chamada do Repository:var list = _repository.Find(courseWithVotes.By());OperadoresCriando outras Specifications, podemos uni-las usando os operadores And e Or, e ate passar parametros para o metodo By():var list = _repository.Find( courseWithVotes.By() .And(courseByExample.By(new Course() { Name = "C#" })));IIdAccessorUma restricao da biblioteca que e todas as suas entidades devem implementar a interface IIdAccessor. Ela descreve um Id unico para aquela entidade.namespace Naskar.QueryOverSpec{ public interface IIdAccessor { long? Id { get; set; } }}Para maioria dos projetos, uma simples classe base abstrata para suas entidades ja resolve essa restricao: public abstract class Entity : IIdAccessor { public virtual long? Id { get; set; } } public class Course : Entity { public Course() { this.Votes = new List<Vote>(); } public virtual string Name { get; set; } public virtual Instructor Instructor { get; set; } public virtual IList<Vote>