public IEngine Build(FluentBuilder baseBuilder, params Type[] types)
        {
            //TODO: Change the line below - should be using a factory of sorts to create the InvokerRegisytry and the ErrorResolber?
            //Pass the factory to the BuilderToken so it can create conditional engines down the track.
            var invokerRegistry = (baseBuilder == null) ? new InvokerRegistry() : CreateInvokerRegistry(baseBuilder.Build().InvokerRegistry, types);
            var errorResolver   = (baseBuilder == null) ? new DefaultErrorResolver() : baseBuilder.Build().ErrorResolver;

            var token = new FluentBuilderToken(
                new Engine(invokerRegistry, errorResolver)
                , _valueResolverFactory ?? new DefaultValueResolverFactory()
                , _culpritResolverFactory ?? new DefaultCulpritResolverFactory()
                );

            foreach (var root in _forScopes)
            {
                var tmp = root;
                while (tmp != null)
                {
                    var fluentScopeAction = tmp.Get(RegistryKeys.FluentScopeAction, null);
                    if (fluentScopeAction != null)
                    {
                        fluentScopeAction.Execute(tmp, token);
                    }
                    tmp = tmp.Child;
                }
            }

            return(token.RootEngine);
        }
        public static void RegisterMessage(FluentScope fluentScope, FluentBuilderToken token)
        {
            var sourceType   = fluentScope.Get(RegistryKeys.SourceType);
            var messageEntry = new MessageEntry(
                sourceType,
                fluentScope.Get(RegistryKeys.SetupExpression, Utilities.ReturnSelf(sourceType)),
                fluentScope.Get(RegistryKeys.Rule, null),
                fluentScope.Get(RegistryKeys.Message));

            token.ErrorResolver.AddEntry(messageEntry);
        }
        public static void RegisterConditional(FluentScope fluentScope, FluentBuilderToken token)
        {
            var conditionalExpression = fluentScope.Get(RegistryKeys.ConditionalExpression);
            var sourceType            = conditionalExpression.Parameters[0].Type;
            var engine           = token.CurrentEngine;
            var conditionalToken = token.Condition();

            var invoker = (IRuleInvoker)Utilities.CreateType(typeof(ConditionalInvoker <>), sourceType)
                          .CreateInstance(conditionalExpression, conditionalToken.IfTrueEngine, conditionalToken.IfFalseEngine);

            engine.InvokerRegistry.RegisterInvoker(invoker);
        }
        public static void RegisterEnumerableComposition(FluentScope fluentScope, FluentBuilderToken token)
        {
            var usingEngine           = fluentScope.Get(RegistryKeys.UsingEngine, token.RootEngine);
            var compositionExpression = fluentScope.Get(RegistryKeys.SetupExpression);
            var sourceType            = compositionExpression.Parameters[0].Type;
            var resultType            = compositionExpression.ReturnType;

            var result = (IRuleInvoker)Utilities.CreateType(typeof(EnumerableCompositionInvoker <,>), sourceType, resultType)
                         .CreateInstance(usingEngine, compositionExpression);

            token.CurrentEngine.InvokerRegistry.RegisterInvoker(result);
        }
        public static void RegisterRule(FluentScope fluentScope, FluentBuilderToken token)
        {
            var rule                            = fluentScope.Get(RegistryKeys.Rule);
            var sourceType                      = fluentScope.Get(RegistryKeys.SourceType);
            var setupExpression                 = fluentScope.Get(RegistryKeys.SetupExpression, Utilities.ReturnSelf(sourceType));
            var valueResolverFactory            = token.ValueResolverFactory;
            var isCrossField                    = fluentScope.Get(RegistryKeys.IsCrossField, false);
            var expressionToInvokeForValidation = isCrossField ? Utilities.ReturnSelf(sourceType) : fluentScope.Get(RegistryKeys.SetupExpression);
            var resultType                      = expressionToInvokeForValidation.ReturnType;
            var valueToValidateResolver         = valueResolverFactory.CreateResolver(expressionToInvokeForValidation);

            var culpritResolver = fluentScope.Get(RegistryKeys.CulpritResolver, token.CulpritResolverFactory.Create(null, setupExpression));
            var result          = (IRuleInvoker)Utilities.CreateType(typeof(RuleInvoker <,>), sourceType, resultType)
                                  .CreateInstance(rule
                                                  , valueToValidateResolver
                                                  , new EquatableExpression(setupExpression)
                                                  , culpritResolver
                                                  );

            token.CurrentEngine.InvokerRegistry.RegisterInvoker(result);
        }
 public static void SwitchToElse(FluentScope fluentScope, FluentBuilderToken token)
 {
     token.Else();
 }
 public void Execute(FluentScope scope, FluentBuilderToken token)
 {
     _action(scope, token);
 }