internal override RuleExpressionResult Evaluate(CodeExpression expression, RuleExecution execution)
        {
            object obj5;
            CodeBinaryOperatorExpression expression2 = (CodeBinaryOperatorExpression)expression;
            object operandValue = RuleExpressionWalker.Evaluate(execution, expression2.Left).Value;
            CodeBinaryOperatorType @operator = expression2.Operator;

            switch (@operator)
            {
            case CodeBinaryOperatorType.BooleanAnd:
                if ((bool)operandValue)
                {
                    return(new RuleLiteralResult(RuleExpressionWalker.Evaluate(execution, expression2.Right).Value));
                }
                return(new RuleLiteralResult(false));

            case CodeBinaryOperatorType.BooleanOr:
                if ((bool)operandValue)
                {
                    return(new RuleLiteralResult(true));
                }
                return(new RuleLiteralResult(RuleExpressionWalker.Evaluate(execution, expression2.Right).Value));
            }
            object obj6 = RuleExpressionWalker.Evaluate(execution, expression2.Right).Value;
            RuleBinaryExpressionInfo info = execution.Validation.ExpressionInfo(expression2) as RuleBinaryExpressionInfo;

            if (info == null)
            {
                InvalidOperationException exception = new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Messages.ExpressionNotValidated, new object[0]));
                exception.Data["ErrorObject"] = expression2;
                throw exception;
            }
            MethodInfo methodInfo = info.MethodInfo;

            if (methodInfo != null)
            {
                if (methodInfo == Literal.ObjectEquality)
                {
                    obj5 = operandValue == obj6;
                }
                else
                {
                    ParameterInfo[] parameters = methodInfo.GetParameters();
                    object[]        objArray   = new object[] { Executor.AdjustType(info.LeftType, operandValue, parameters[0].ParameterType), Executor.AdjustType(info.RightType, obj6, parameters[1].ParameterType) };
                    obj5 = methodInfo.Invoke(null, objArray);
                }
            }
            else
            {
                obj5 = EvaluateBinaryOperation(expression2, info.LeftType, operandValue, @operator, info.RightType, obj6);
            }
            return(new RuleLiteralResult(obj5));
        }
        internal override void AnalyzeUsage(CodeExpression expression, RuleAnalysis analysis, bool isRead, bool isWritten, RulePathQualifier qualifier)
        {
            CodeBinaryOperatorExpression expression2 = (CodeBinaryOperatorExpression)expression;
            RuleBinaryExpressionInfo     info        = analysis.Validation.ExpressionInfo(expression2) as RuleBinaryExpressionInfo;

            if (info != null)
            {
                MethodInfo methodInfo = info.MethodInfo;
                if (methodInfo != null)
                {
                    List <CodeExpression>    attributedExprs = new List <CodeExpression>();
                    CodeExpressionCollection argExprs        = new CodeExpressionCollection();
                    argExprs.Add(expression2.Left);
                    argExprs.Add(expression2.Right);
                    CodeExpression targetExpr = new CodeTypeReferenceExpression(methodInfo.DeclaringType);
                    analysis.AnalyzeRuleAttributes(methodInfo, targetExpr, qualifier, argExprs, methodInfo.GetParameters(), attributedExprs);
                }
            }
            RuleExpressionWalker.AnalyzeUsage(analysis, expression2.Left, true, false, null);
            RuleExpressionWalker.AnalyzeUsage(analysis, expression2.Right, true, false, null);
        }
        internal override RuleExpressionInfo Validate(CodeExpression expression, RuleValidation validation, bool isWritten)
        {
            ValidationError error;
            CodeBinaryOperatorExpression newParent = (CodeBinaryOperatorExpression)expression;

            if (!validation.PushParentExpression(newParent))
            {
                return(null);
            }
            if (isWritten)
            {
                error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.CannotWriteToExpression, new object[] { typeof(CodeBinaryOperatorExpression).ToString() }), 0x17a);
                error.UserData["ErrorObject"] = newParent;
                validation.Errors.Add(error);
            }
            RuleExpressionInfo info  = null;
            RuleExpressionInfo info2 = null;

            if (newParent.Left == null)
            {
                error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.NullBinaryOpLHS, new object[] { newParent.Operator.ToString() }), 0x541);
                error.UserData["ErrorObject"] = newParent;
                validation.Errors.Add(error);
            }
            else
            {
                if (newParent.Left is CodeTypeReferenceExpression)
                {
                    error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.CodeExpressionNotHandled, new object[] { newParent.Left.GetType().FullName }), 0x548);
                    error.UserData["ErrorObject"] = newParent.Left;
                    validation.AddError(error);
                    return(null);
                }
                info = RuleExpressionWalker.Validate(validation, newParent.Left, false);
            }
            if (newParent.Right == null)
            {
                error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.NullBinaryOpRHS, new object[] { newParent.Operator.ToString() }), 0x543);
                error.UserData["ErrorObject"] = newParent;
                validation.Errors.Add(error);
            }
            else
            {
                if (newParent.Right is CodeTypeReferenceExpression)
                {
                    error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.CodeExpressionNotHandled, new object[] { newParent.Right.GetType().FullName }), 0x548);
                    error.UserData["ErrorObject"] = newParent.Right;
                    validation.AddError(error);
                    return(null);
                }
                info2 = RuleExpressionWalker.Validate(validation, newParent.Right, false);
            }
            validation.PopParentExpression();
            RuleBinaryExpressionInfo info3 = null;

            if ((info != null) && (info2 != null))
            {
                Type expressionType = info.ExpressionType;
                Type rhs            = info2.ExpressionType;
                switch (newParent.Operator)
                {
                case CodeBinaryOperatorType.Add:
                case CodeBinaryOperatorType.Subtract:
                case CodeBinaryOperatorType.Multiply:
                case CodeBinaryOperatorType.Divide:
                case CodeBinaryOperatorType.Modulus:
                case CodeBinaryOperatorType.BitwiseOr:
                case CodeBinaryOperatorType.BitwiseAnd:
                    info3 = ArithmeticLiteral.ResultType(newParent.Operator, expressionType, newParent.Left, rhs, newParent.Right, validation, out error);
                    if (info3 == null)
                    {
                        if ((!(expressionType == typeof(ulong)) || !PromotionPossible(rhs, newParent.Right)) && (!(rhs == typeof(ulong)) || !PromotionPossible(expressionType, newParent.Left)))
                        {
                            error.UserData["ErrorObject"] = newParent;
                            validation.Errors.Add(error);
                        }
                        else
                        {
                            info3 = new RuleBinaryExpressionInfo(expressionType, rhs, typeof(ulong));
                        }
                    }
                    goto Label_063E;

                case CodeBinaryOperatorType.IdentityInequality:
                case CodeBinaryOperatorType.IdentityEquality:
                    info3 = new RuleBinaryExpressionInfo(expressionType, rhs, typeof(bool));
                    goto Label_063E;

                case CodeBinaryOperatorType.ValueEquality:
                    info3 = Literal.AllowedComparison(expressionType, newParent.Left, rhs, newParent.Right, newParent.Operator, validation, out error);
                    if (info3 == null)
                    {
                        if ((!(expressionType == typeof(ulong)) || !PromotionPossible(rhs, newParent.Right)) && (!(rhs == typeof(ulong)) || !PromotionPossible(expressionType, newParent.Left)))
                        {
                            error.UserData["ErrorObject"] = newParent;
                            validation.Errors.Add(error);
                        }
                        else
                        {
                            info3 = new RuleBinaryExpressionInfo(expressionType, rhs, typeof(bool));
                        }
                    }
                    goto Label_063E;

                case CodeBinaryOperatorType.BooleanOr:
                case CodeBinaryOperatorType.BooleanAnd:
                    info3 = new RuleBinaryExpressionInfo(expressionType, rhs, typeof(bool));
                    if (expressionType != typeof(bool))
                    {
                        error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.LogicalOpBadTypeLHS, new object[] { newParent.Operator.ToString(), (expressionType == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(expressionType) }), 0x542);
                        error.UserData["ErrorObject"] = newParent;
                        validation.Errors.Add(error);
                        info3 = null;
                    }
                    if (rhs != typeof(bool))
                    {
                        error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.LogicalOpBadTypeRHS, new object[] { newParent.Operator.ToString(), (rhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(rhs) }), 0x544);
                        error.UserData["ErrorObject"] = newParent;
                        validation.Errors.Add(error);
                        info3 = null;
                    }
                    goto Label_063E;

                case CodeBinaryOperatorType.LessThan:
                case CodeBinaryOperatorType.LessThanOrEqual:
                case CodeBinaryOperatorType.GreaterThan:
                case CodeBinaryOperatorType.GreaterThanOrEqual:
                    info3 = Literal.AllowedComparison(expressionType, newParent.Left, rhs, newParent.Right, newParent.Operator, validation, out error);
                    if (info3 == null)
                    {
                        if ((!(expressionType == typeof(ulong)) || !PromotionPossible(rhs, newParent.Right)) && (!(rhs == typeof(ulong)) || !PromotionPossible(expressionType, newParent.Left)))
                        {
                            error.UserData["ErrorObject"] = newParent;
                            validation.Errors.Add(error);
                        }
                        else
                        {
                            info3 = new RuleBinaryExpressionInfo(expressionType, rhs, typeof(bool));
                        }
                    }
                    goto Label_063E;
                }
                error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.BinaryOpNotSupported, new object[] { newParent.Operator.ToString() }), 0x548);
                error.UserData["ErrorObject"] = newParent;
                validation.Errors.Add(error);
            }
Label_063E:
            if (info3 != null)
            {
                MethodInfo methodInfo = info3.MethodInfo;
                if (methodInfo == null)
                {
                    return(info3);
                }
                object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuleAttribute), true);
                if ((customAttributes == null) || (customAttributes.Length <= 0))
                {
                    return(info3);
                }
                Stack <MemberInfo> stack = new Stack <MemberInfo>();
                stack.Push(methodInfo);
                bool flag = true;
                foreach (RuleAttribute attribute in customAttributes)
                {
                    if (!attribute.Validate(validation, methodInfo, methodInfo.DeclaringType, methodInfo.GetParameters()))
                    {
                        flag = false;
                    }
                }
                stack.Pop();
                if (!flag)
                {
                    return(null);
                }
            }
            return(info3);
        }
        internal override RuleExpressionInfo Validate(CodeExpression expression, RuleValidation validation, bool isWritten)
        {
            ValidationError error;
            CodeBinaryOperatorExpression newParent = (CodeBinaryOperatorExpression) expression;
            if (!validation.PushParentExpression(newParent))
            {
                return null;
            }
            if (isWritten)
            {
                error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.CannotWriteToExpression, new object[] { typeof(CodeBinaryOperatorExpression).ToString() }), 0x17a);
                error.UserData["ErrorObject"] = newParent;
                validation.Errors.Add(error);
            }
            RuleExpressionInfo info = null;
            RuleExpressionInfo info2 = null;
            if (newParent.Left == null)
            {
                error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.NullBinaryOpLHS, new object[] { newParent.Operator.ToString() }), 0x541);
                error.UserData["ErrorObject"] = newParent;
                validation.Errors.Add(error);
            }
            else
            {
                if (newParent.Left is CodeTypeReferenceExpression)
                {
                    error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.CodeExpressionNotHandled, new object[] { newParent.Left.GetType().FullName }), 0x548);
                    error.UserData["ErrorObject"] = newParent.Left;
                    validation.AddError(error);
                    return null;
                }
                info = RuleExpressionWalker.Validate(validation, newParent.Left, false);
            }
            if (newParent.Right == null)
            {
                error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.NullBinaryOpRHS, new object[] { newParent.Operator.ToString() }), 0x543);
                error.UserData["ErrorObject"] = newParent;
                validation.Errors.Add(error);
            }
            else
            {
                if (newParent.Right is CodeTypeReferenceExpression)
                {
                    error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.CodeExpressionNotHandled, new object[] { newParent.Right.GetType().FullName }), 0x548);
                    error.UserData["ErrorObject"] = newParent.Right;
                    validation.AddError(error);
                    return null;
                }
                info2 = RuleExpressionWalker.Validate(validation, newParent.Right, false);
            }
            validation.PopParentExpression();
            RuleBinaryExpressionInfo info3 = null;
            if ((info != null) && (info2 != null))
            {
                Type expressionType = info.ExpressionType;
                Type rhs = info2.ExpressionType;
                switch (newParent.Operator)
                {
                    case CodeBinaryOperatorType.Add:
                    case CodeBinaryOperatorType.Subtract:
                    case CodeBinaryOperatorType.Multiply:
                    case CodeBinaryOperatorType.Divide:
                    case CodeBinaryOperatorType.Modulus:
                    case CodeBinaryOperatorType.BitwiseOr:
                    case CodeBinaryOperatorType.BitwiseAnd:
                        info3 = ArithmeticLiteral.ResultType(newParent.Operator, expressionType, newParent.Left, rhs, newParent.Right, validation, out error);
                        if (info3 == null)
                        {
                            if ((!(expressionType == typeof(ulong)) || !PromotionPossible(rhs, newParent.Right)) && (!(rhs == typeof(ulong)) || !PromotionPossible(expressionType, newParent.Left)))
                            {
                                error.UserData["ErrorObject"] = newParent;
                                validation.Errors.Add(error);
                            }
                            else
                            {
                                info3 = new RuleBinaryExpressionInfo(expressionType, rhs, typeof(ulong));
                            }
                        }
                        goto Label_063E;

                    case CodeBinaryOperatorType.IdentityInequality:
                    case CodeBinaryOperatorType.IdentityEquality:
                        info3 = new RuleBinaryExpressionInfo(expressionType, rhs, typeof(bool));
                        goto Label_063E;

                    case CodeBinaryOperatorType.ValueEquality:
                        info3 = Literal.AllowedComparison(expressionType, newParent.Left, rhs, newParent.Right, newParent.Operator, validation, out error);
                        if (info3 == null)
                        {
                            if ((!(expressionType == typeof(ulong)) || !PromotionPossible(rhs, newParent.Right)) && (!(rhs == typeof(ulong)) || !PromotionPossible(expressionType, newParent.Left)))
                            {
                                error.UserData["ErrorObject"] = newParent;
                                validation.Errors.Add(error);
                            }
                            else
                            {
                                info3 = new RuleBinaryExpressionInfo(expressionType, rhs, typeof(bool));
                            }
                        }
                        goto Label_063E;

                    case CodeBinaryOperatorType.BooleanOr:
                    case CodeBinaryOperatorType.BooleanAnd:
                        info3 = new RuleBinaryExpressionInfo(expressionType, rhs, typeof(bool));
                        if (expressionType != typeof(bool))
                        {
                            error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.LogicalOpBadTypeLHS, new object[] { newParent.Operator.ToString(), (expressionType == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(expressionType) }), 0x542);
                            error.UserData["ErrorObject"] = newParent;
                            validation.Errors.Add(error);
                            info3 = null;
                        }
                        if (rhs != typeof(bool))
                        {
                            error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.LogicalOpBadTypeRHS, new object[] { newParent.Operator.ToString(), (rhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(rhs) }), 0x544);
                            error.UserData["ErrorObject"] = newParent;
                            validation.Errors.Add(error);
                            info3 = null;
                        }
                        goto Label_063E;

                    case CodeBinaryOperatorType.LessThan:
                    case CodeBinaryOperatorType.LessThanOrEqual:
                    case CodeBinaryOperatorType.GreaterThan:
                    case CodeBinaryOperatorType.GreaterThanOrEqual:
                        info3 = Literal.AllowedComparison(expressionType, newParent.Left, rhs, newParent.Right, newParent.Operator, validation, out error);
                        if (info3 == null)
                        {
                            if ((!(expressionType == typeof(ulong)) || !PromotionPossible(rhs, newParent.Right)) && (!(rhs == typeof(ulong)) || !PromotionPossible(expressionType, newParent.Left)))
                            {
                                error.UserData["ErrorObject"] = newParent;
                                validation.Errors.Add(error);
                            }
                            else
                            {
                                info3 = new RuleBinaryExpressionInfo(expressionType, rhs, typeof(bool));
                            }
                        }
                        goto Label_063E;
                }
                error = new ValidationError(string.Format(CultureInfo.CurrentCulture, Messages.BinaryOpNotSupported, new object[] { newParent.Operator.ToString() }), 0x548);
                error.UserData["ErrorObject"] = newParent;
                validation.Errors.Add(error);
            }
        Label_063E:
            if (info3 != null)
            {
                MethodInfo methodInfo = info3.MethodInfo;
                if (methodInfo == null)
                {
                    return info3;
                }
                object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuleAttribute), true);
                if ((customAttributes == null) || (customAttributes.Length <= 0))
                {
                    return info3;
                }
                Stack<MemberInfo> stack = new Stack<MemberInfo>();
                stack.Push(methodInfo);
                bool flag = true;
                foreach (RuleAttribute attribute in customAttributes)
                {
                    if (!attribute.Validate(validation, methodInfo, methodInfo.DeclaringType, methodInfo.GetParameters()))
                    {
                        flag = false;
                    }
                }
                stack.Pop();
                if (!flag)
                {
                    return null;
                }
            }
            return info3;
        }
Exemplo n.º 5
0
        internal override RuleExpressionInfo Validate(CodeExpression expression, RuleValidation validation, bool isWritten)
        {
            string message;
            ValidationError error;

            CodeBinaryOperatorExpression binaryExpr = (CodeBinaryOperatorExpression)expression;

            // Early exit from this if a cycle is detected.
            if (!validation.PushParentExpression(binaryExpr))
                return null;

            if (isWritten)
            {
                message = string.Format(CultureInfo.CurrentCulture, Messages.CannotWriteToExpression, typeof(CodeBinaryOperatorExpression).ToString());
                error = new ValidationError(message, ErrorNumbers.Error_InvalidAssignTarget);
                error.UserData[RuleUserDataKeys.ErrorObject] = binaryExpr;
                validation.Errors.Add(error);
            }

            RuleExpressionInfo lhsExprInfo = null;
            RuleExpressionInfo rhsExprInfo = null;

            if (binaryExpr.Left == null)
            {
                message = string.Format(CultureInfo.CurrentCulture, Messages.NullBinaryOpLHS, binaryExpr.Operator.ToString());
                error = new ValidationError(message, ErrorNumbers.Error_LeftOperandMissing);
                error.UserData[RuleUserDataKeys.ErrorObject] = binaryExpr;
                validation.Errors.Add(error);
            }
            else
            {
                if (binaryExpr.Left is CodeTypeReferenceExpression)
                {
                    message = string.Format(CultureInfo.CurrentCulture, Messages.CodeExpressionNotHandled, binaryExpr.Left.GetType().FullName);
                    error = new ValidationError(message, ErrorNumbers.Error_CodeExpressionNotHandled);
                    error.UserData[RuleUserDataKeys.ErrorObject] = binaryExpr.Left;
                    validation.AddError(error);
                    return null;
                }

                lhsExprInfo = RuleExpressionWalker.Validate(validation, binaryExpr.Left, false);
            }

            if (binaryExpr.Right == null)
            {
                message = string.Format(CultureInfo.CurrentCulture, Messages.NullBinaryOpRHS, binaryExpr.Operator.ToString());
                error = new ValidationError(message, ErrorNumbers.Error_RightOperandMissing);
                error.UserData[RuleUserDataKeys.ErrorObject] = binaryExpr;
                validation.Errors.Add(error);
            }
            else
            {
                if (binaryExpr.Right is CodeTypeReferenceExpression)
                {
                    message = string.Format(CultureInfo.CurrentCulture, Messages.CodeExpressionNotHandled, binaryExpr.Right.GetType().FullName);
                    error = new ValidationError(message, ErrorNumbers.Error_CodeExpressionNotHandled);
                    error.UserData[RuleUserDataKeys.ErrorObject] = binaryExpr.Right;
                    validation.AddError(error);
                    return null;
                }

                rhsExprInfo = RuleExpressionWalker.Validate(validation, binaryExpr.Right, false);
            }

            validation.PopParentExpression();

            RuleBinaryExpressionInfo resultExprInfo = null;

            if (lhsExprInfo != null && rhsExprInfo != null)
            {
                Type lhsType = lhsExprInfo.ExpressionType;
                Type rhsType = rhsExprInfo.ExpressionType;

                switch (binaryExpr.Operator)
                {
                    case CodeBinaryOperatorType.Add:
                    case CodeBinaryOperatorType.Subtract:
                    case CodeBinaryOperatorType.Multiply:
                    case CodeBinaryOperatorType.Divide:
                    case CodeBinaryOperatorType.Modulus:
                    case CodeBinaryOperatorType.BitwiseAnd:
                    case CodeBinaryOperatorType.BitwiseOr:
                        resultExprInfo = ArithmeticLiteral.ResultType(binaryExpr.Operator, lhsType, binaryExpr.Left, rhsType, binaryExpr.Right, validation, out error);
                        if (resultExprInfo == null)
                        {
                            // check if constants are used with ulongs, as we should do some extra "conversions"
                            if (((lhsType == typeof(ulong)) && (PromotionPossible(rhsType, binaryExpr.Right)))
                                || ((rhsType == typeof(ulong)) && (PromotionPossible(lhsType, binaryExpr.Left))))
                            {
                                resultExprInfo = new RuleBinaryExpressionInfo(lhsType, rhsType, typeof(ulong));
                            }
                            else
                            {
                                error.UserData[RuleUserDataKeys.ErrorObject] = binaryExpr;
                                validation.Errors.Add(error);
                            }
                        }
                        break;

                    case CodeBinaryOperatorType.IdentityEquality:
                    case CodeBinaryOperatorType.IdentityInequality:
                        resultExprInfo = new RuleBinaryExpressionInfo(lhsType, rhsType, typeof(bool));
                        break;

                    case CodeBinaryOperatorType.ValueEquality:
                        resultExprInfo = Literal.AllowedComparison(lhsType, binaryExpr.Left, rhsType, binaryExpr.Right, binaryExpr.Operator, validation, out error);
                        if (resultExprInfo == null)
                        {
                            // check if constants are used with ulongs, as we should do some extra "conversions"
                            if (((lhsType == typeof(ulong)) && (PromotionPossible(rhsType, binaryExpr.Right)))
                                || ((rhsType == typeof(ulong)) && (PromotionPossible(lhsType, binaryExpr.Left))))
                            {
                                resultExprInfo = new RuleBinaryExpressionInfo(lhsType, rhsType, typeof(bool));
                            }
                            else
                            {
                                error.UserData[RuleUserDataKeys.ErrorObject] = binaryExpr;
                                validation.Errors.Add(error);
                            }
                        }
                        break;

                    case CodeBinaryOperatorType.LessThan:
                    case CodeBinaryOperatorType.LessThanOrEqual:
                    case CodeBinaryOperatorType.GreaterThan:
                    case CodeBinaryOperatorType.GreaterThanOrEqual:
                        resultExprInfo = Literal.AllowedComparison(lhsType, binaryExpr.Left, rhsType, binaryExpr.Right, binaryExpr.Operator, validation, out error);
                        if (resultExprInfo == null)
                        {
                            // check if constants are used with ulongs, as we should do some extra "conversions"
                            if (((lhsType == typeof(ulong)) && (PromotionPossible(rhsType, binaryExpr.Right)))
                                || ((rhsType == typeof(ulong)) && (PromotionPossible(lhsType, binaryExpr.Left))))
                            {
                                resultExprInfo = new RuleBinaryExpressionInfo(lhsType, rhsType, typeof(bool));
                            }
                            else
                            {
                                error.UserData[RuleUserDataKeys.ErrorObject] = binaryExpr;
                                validation.Errors.Add(error);
                            }
                        }
                        break;

                    case CodeBinaryOperatorType.BooleanAnd:
                    case CodeBinaryOperatorType.BooleanOr:
                        resultExprInfo = new RuleBinaryExpressionInfo(lhsType, rhsType, typeof(bool));
                        if (lhsType != typeof(bool))
                        {
                            message = string.Format(CultureInfo.CurrentCulture, Messages.LogicalOpBadTypeLHS, binaryExpr.Operator.ToString(),
                                (lhsType == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(lhsType));
                            error = new ValidationError(message, ErrorNumbers.Error_LeftOperandInvalidType);
                            error.UserData[RuleUserDataKeys.ErrorObject] = binaryExpr;
                            validation.Errors.Add(error);
                            resultExprInfo = null;
                        }
                        if (rhsType != typeof(bool))
                        {
                            message = string.Format(CultureInfo.CurrentCulture, Messages.LogicalOpBadTypeRHS, binaryExpr.Operator.ToString(),
                                (rhsType == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(rhsType));
                            error = new ValidationError(message, ErrorNumbers.Error_RightOperandInvalidType);
                            error.UserData[RuleUserDataKeys.ErrorObject] = binaryExpr;
                            validation.Errors.Add(error);
                            resultExprInfo = null;
                        }
                        break;

                    default:
                        {
                            message = string.Format(CultureInfo.CurrentCulture, Messages.BinaryOpNotSupported, binaryExpr.Operator.ToString());
                            error = new ValidationError(message, ErrorNumbers.Error_CodeExpressionNotHandled);
                            error.UserData[RuleUserDataKeys.ErrorObject] = binaryExpr;
                            validation.Errors.Add(error);
                        }
                        break;
                }
            }

            // Validate any RuleAttributes, if present.
            if (resultExprInfo != null)
            {
                MethodInfo method = resultExprInfo.MethodInfo;
                if (method != null)
                {
                    object[] attrs = method.GetCustomAttributes(typeof(RuleAttribute), true);
                    if (attrs != null && attrs.Length > 0)
                    {
                        Stack<MemberInfo> methodStack = new Stack<MemberInfo>();
                        methodStack.Push(method);

                        bool allAttributesValid = true;
                        foreach (RuleAttribute ruleAttr in attrs)
                        {
                            if (!ruleAttr.Validate(validation, method, method.DeclaringType, method.GetParameters()))
                                allAttributesValid = false;
                        }

                        methodStack.Pop();

                        if (!allAttributesValid)
                            return null;
                    }
                }
            }

            return resultExprInfo;
        }