Spec Pattern project consists of only five classes and in most of the cases you will only have to know about one.

Creating a new Specification

Simply inherit from Specification<T> and override DefinePredicate method which should return the predicate that defines your specification:

        public class Project
            public string Name{ get; set; }

            public int Features { get; set; }

            public int Followers { get; set; }

            public bool Stable { get; set; }

        public class CoolProjectSpec : Specification<Project>
            protected override Expression<Func<Project, bool>> DefinePredicate()
                return p => p.Features >= 5;

Of course you can work with instance fields inside your predicate if needed (usually you will):

        public class CoolProjectSpec : Specification<Project>
            private readonly int minFeaturesToBeCool;
            public CoolProjectSpec(int minFeaturesToBeCool)
                this.minFeaturesToBeCool = minFeaturesToBeCool;

            protected override Expression<Func<Project, bool>> DefinePredicate()
                return p => p.Features >= minFeaturesToBeCool;

Combining specifications

The main advantage of using specifications is the ability to combine them as if they were predicates, relying on C# operator overloading we can do this with a clean syntax:

            Specification<Project> coolProjectSpec = new CoolProjectSpec(5);
            Specification<Project> popularProjectSpec = new PopularProjectSpec();
            Specification<Project> trustableProjectSpec = new TrustableProjectSpec();

            var project = new Project { Features = 5, Followers = 250, Stable = true };
            //Check if project rules
            var projectRulesSpec = coolProjectSpec & popularProjectSpec 
                                    & trustableProjectSpec;

            // Check if project is cool and trustable but unpopular (i know that story)
            var greatButUnpopularSpec = coolProjectSpec & trustableProjectSpec 
                                        & !popularProjectSpec;

            // Check if project is either cool or popular but it should be trustable
            var atLeastTrustableSpec = (coolProjectSpec | popularProjectSpec)
                                        & trustableProjectSpec ;

ORM integration

The best part is you dont have to do anything to integrate it with your ORM; if it supports IQueryable you are done:

            // Use the same specs but now to query database with an ORM
            var allGreatButUnpopularProjects = Repository.Query<Project>()

Last edited Apr 10, 2012 at 3:37 PM by jorgehmv, version 3


No comments yet.