Tree structure that describes RuleValidators and their relations to one another (i.e. And / Or)
        public void CreateExpression_DateOutsideOfWindowAndIsMonday_BuildsExpression(int year, int month, int day, bool validates, int numberOfErrorMsg)
        {
            // Test: (DateTime d) => (d < floorDate | d > ceilingDate) & d.DayOfWeek == DayOfWeek.Monday
            var floorDate = new DateTime(2010, 2, 1);
            var ceilingDate = new DateTime(2010, 3, 1);
            var testDate = new DateTime(year, month, day);

            // build rule / rule node for "d.DayOfWeek == DayOfWeek.Monday
            var dateOneMondayRule = new CustomRule<CalendarEvent, DateTime>((c, d) => d.DayOfWeek == DayOfWeek.Monday);
            dateOneMondayRule.Message = "Date does not fall on a Monday.";
            var dateOneMondayRuleNode = new RuleNode(dateOneMondayRule);

            // build rules / rule nodes for "d < floorDate | d > ceilingDate"
            var rangeRuleNode = new RuleNode(new LessThan<CalendarEvent, DateTime>(floorDate));
            rangeRuleNode.OrChild(new RuleNode(new GreaterThan<CalendarEvent, DateTime>(ceilingDate)));

            // put the rules / rule nodes together using a group to enforce the "or" precidence over the "and"
            var groupNode = new GroupNode(rangeRuleNode);
            groupNode.AndChild(dateOneMondayRuleNode);

            var tree = new RuleTree<CalendarEvent, DateTime>(groupNode);

            Assert.That(tree.LambdaExpression, Is.Not.Null);

            var context = BuildContextForCalendarEventStartDate(testDate);
            var notification = new ValidationNotification();
            var isValid = tree.LambdaExpression(context, null, notification);

            Assert.That(isValid, Is.EqualTo(validates));
        }
        public Func <RuleValidatorContext <T, TProperty>, SpecificationContainer, ValidationNotification, bool> CreateExpression(RuleTree <T, TProperty> tree)
        {
            var contextParam          = Expression.Parameter(typeof(RuleValidatorContext <T, TProperty>), "context");
            var specContainerParam    = Expression.Parameter(typeof(SpecificationContainer), "container");
            var specNotificationParam = Expression.Parameter(typeof(ValidationNotification), "notification");

            var expression   = BuildExpression(tree.Root, contextParam, specContainerParam, specNotificationParam);
            var lambda       = Expression.Lambda(expression, new ParameterExpression[] { contextParam, specContainerParam, specNotificationParam });
            var compiledFunc = lambda.Compile() as Func <RuleValidatorContext <T, TProperty>, SpecificationContainer, ValidationNotification, bool>;

            return(compiledFunc);
        }