public static MutatorsConfigurator <TRoot, TChild, TValue> MustBelongTo <TRoot, TChild, TValue>(
            this MutatorsConfigurator <TRoot, TChild, TValue> configurator,
            IEnumerable <TValue> values,
            IEqualityComparer <TValue> comparer = null,
            int priority = 0,
            ValidationResultType type = ValidationResultType.Error)
        {
            var        methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var        pathToValue    = (Expression <Func <TRoot, TValue> >)methodReplacer.Visit(configurator.PathToValue);
            var        pathToChild    = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild);
            Expression contains       = comparer == null
                                      ? Expression.Call(containsMethod.MakeGenericMethod(typeof(TValue)), Expression.Constant(values), pathToValue.Body)
                                      : Expression.Call(containsWithComparerMethod.MakeGenericMethod(typeof(TValue)), Expression.Constant(values), pathToValue.Body, Expression.Constant(comparer));

            var condition = Expression.Convert(Expression.Not(contains), typeof(bool?));
            var message   = Expression.MemberInit(Expression.New(typeof(ValueMustBelongToText)),
                                                  Expression.Bind(typeof(ValueMustBelongToText).GetMember("Value").Single(), pathToValue.Body),
                                                  Expression.Bind(typeof(ValueMustBelongToText).GetMember("Values").Single(), Expression.Constant(values.Cast <object>().ToArray())));

            configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToValue.Parameters), Expression.Lambda <Func <TRoot, MultiLanguageTextBase> >(message, pathToChild.Parameters), type));
            return(configurator);
        }
        public static MutatorsConfigurator <TRoot, TChild, string> LengthInRange <TRoot, TChild>(
            this MutatorsConfigurator <TRoot, TChild, string> configurator,
            int fromLength,
            int toLength,
            MultiLanguageTextBase title,
            int priority = 0,
            ValidationResultType type = ValidationResultType.Error)
        {
            var methodReplacer  = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod);
            var pathToValue     = (Expression <Func <TRoot, string> >)methodReplacer.Visit(configurator.PathToValue);
            var leftExpression  = Expression.LessThan(Expression.MakeMemberAccess(pathToValue.Body, stringLengthProperty), Expression.Constant(fromLength));
            var rigthExpression = Expression.GreaterThan(Expression.MakeMemberAccess(pathToValue.Body, stringLengthProperty), Expression.Constant(toLength));

            var condition = Expression.Convert(Expression.OrElse(leftExpression, rigthExpression), typeof(bool?));
            var message   = Expression.Lambda <Func <TRoot, MultiLanguageTextBase> >(Expression.MemberInit(
                                                                                         Expression.New(typeof(LengthOutOfRangeText)),
                                                                                         Expression.Bind(lengthOutOfRangeTextToProperty, Expression.Constant(toLength, typeof(int?))),
                                                                                         Expression.Bind(lengthOutOfRangeTextFromProperty, Expression.Constant(fromLength, typeof(int?))),
                                                                                         Expression.Bind(lengthOutOfRangeTextTitleProperty, Expression.Constant(title, typeof(MultiLanguageTextBase)))), pathToValue.Parameters);

            configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToValue.Parameters), message, type));
            return(configurator);
        }
        public static void FilledExactlyOneOf <TRoot, TChild>(
            this MutatorsConfigurator <TRoot, TChild, TChild> configurator,
            Expression <Func <TChild, object[]> > targets,
            Expression <Func <TChild, MultiLanguageTextBase> > message,
            int priority = 0,
            ValidationResultType type = ValidationResultType.Error)
        {
            Expression sum = null;

            if (targets.Body.NodeType != ExpressionType.NewArrayInit)
            {
                throw new InvalidOperationException("Expected new array creation");
            }
            Expression lcp = null;

            foreach (var expression in ((NewArrayExpression)targets.Body).Expressions)
            {
                var target = expression.NodeType == ExpressionType.Convert ? ((UnaryExpression)expression).Operand : expression;
                if (target.Type.IsValueType && !IsNullable(target.Type))
                {
                    throw new InvalidOperationException("Type '" + target.Type + "' cannot be null");
                }
                lcp = lcp == null ? target : lcp.LCP(target);
                Expression current = Expression.Condition(Expression.Equal(target, Expression.Constant(null, target.Type)), Expression.Constant(0), Expression.Constant(1));
                sum = sum == null ? current : Expression.Add(sum, current);
            }

            if (sum == null)
            {
                return;
            }
            Expression condition = Expression.NotEqual(sum, Expression.Constant(1));

            configurator.SetMutator(configurator.PathToChild.Merge(Expression.Lambda(lcp, targets.Parameters)).Body, configurator.PathToChild.Merge(targets).Body, InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, configurator.PathToChild.Merge(Expression.Lambda <Func <TChild, bool?> >(Expression.Convert(condition, typeof(bool?)), targets.Parameters)), configurator.PathToChild.Merge(message), type));
        }