コード例 #1
0
 private static void DumpExpression(CodeExpression e)
 {
     /*
      *               System.CodeDom.CodeArgumentReferenceExpression
      *                 System.CodeDom.CodeArrayCreateExpression
      *                 System.CodeDom.CodeArrayIndexerExpression
      *                 System.CodeDom.CodeBaseReferenceExpression
      *                 System.CodeDom.CodeBinaryOperatorExpression
      *                 System.CodeDom.CodeCastExpression
      *                 System.CodeDom.CodeDefaultValueExpression
      *                 System.CodeDom.CodeDelegateCreateExpression
      *                 System.CodeDom.CodeDelegateInvokeExpression
      *                 System.CodeDom.CodeDirectionExpression
      *                 System.CodeDom.CodeEventReferenceExpression
      *                 System.CodeDom.CodeFieldReferenceExpression
      *                 System.CodeDom.CodeIndexerExpression
      *                 System.CodeDom.CodeMethodInvokeExpression
      *                 System.CodeDom.CodeMethodReferenceExpression
      *                 System.CodeDom.CodeObjectCreateExpression
      *                 System.CodeDom.CodeParameterDeclarationExpression
      *                 System.CodeDom.CodePrimitiveExpression
      *                 System.CodeDom.CodePropertyReferenceExpression
      *                 System.CodeDom.CodePropertySetValueReferenceExpression
      *                 System.CodeDom.CodeSnippetExpression
      *                 System.CodeDom.CodeThisReferenceExpression
      *                 System.CodeDom.CodeTypeOfExpression
      *                 System.CodeDom.CodeTypeReferenceExpression
      *                 System.CodeDom.CodeVariableReferenceExpression
      */
     if (e == null)
     {
         return;
     }
     if (e is CodeFieldReferenceExpression cfre)
     {
         DumpExpression(cfre.TargetObject);
         WriteLineIndent("F: " + cfre.FieldName);
     }
     else if (e is CodeObjectCreateExpression coce)
     {
         var tr = coce.CreateType as CodeTypeReference;
         WriteLineIndent(tr.BaseType + "{}");
         DumpExpressionList(coce.Parameters);
     }
     else if (e is CodeMethodInvokeExpression cmie)
     {
         DumpExpression(cmie.Method.TargetObject);
         WriteLineIndent("M: " + cmie.Method.MethodName);
         DumpExpressionList(cmie.Parameters);
     }
     else if (e is CodePropertyReferenceExpression cpre)
     {
         DumpExpression(cpre.TargetObject);
         WriteLineIndent("P: " + cpre.PropertyName);
     }
     else if (e is CodePrimitiveExpression cpe)
     {
         WriteLineIndent(cpe.ToString());
         WriteLineIndent(cpe.Value.ToString());
     }
     else if (e is CodeCastExpression cce)
     {
         WriteLineIndent(cce.TargetType.ToString());
         DumpExpression(cce.Expression);
     }
     else if (e is CodeThisReferenceExpression)
     {
         WriteLineIndent("SELF");
     }
     else if (e is CodeBinaryOperatorExpression cboe)
     {
         DumpExpression(cboe.Left);
         CodeBinaryOperatorType opType = cboe.Operator;
         WriteLineIndent(opType.ToString());
         DumpExpression(cboe.Right);
     }
     else if (e is CodeTypeReferenceExpression ctre)
     {
         var tr = ctre.Type;
         WriteLineIndent(tr.BaseType);
     }
     else if (e is CodeBaseReferenceExpression)
     {
         WriteLineIndent("SUPER");
     }
     else
     {
         WriteLineIndent(e.GetType().FullName);
     }
 }
コード例 #2
0
        private static object EvaluateBinaryOperation(CodeBinaryOperatorExpression binaryExpr, Type lhsType, object lhsValue, CodeBinaryOperatorType operation, Type rhsType, object rhsValue)
        {
            Literal                 literal;
            Literal                 literal2;
            ArithmeticLiteral       literal3;
            ArithmeticLiteral       literal4;
            RuleEvaluationException exception;

            switch (operation)
            {
            case CodeBinaryOperatorType.Add:
                literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                if (literal3 == null)
                {
                    break;
                }
                literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                if (literal4 == null)
                {
                    break;
                }
                return(literal3.Add(literal4));

            case CodeBinaryOperatorType.Subtract:
                literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                if (literal3 == null)
                {
                    break;
                }
                literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                if (literal4 == null)
                {
                    break;
                }
                return(literal3.Subtract(literal4));

            case CodeBinaryOperatorType.Multiply:
                literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                if (literal3 == null)
                {
                    break;
                }
                literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                if (literal4 == null)
                {
                    break;
                }
                return(literal3.Multiply(literal4));

            case CodeBinaryOperatorType.Divide:
                literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                if (literal3 == null)
                {
                    break;
                }
                literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                if (literal4 == null)
                {
                    break;
                }
                return(literal3.Divide(literal4));

            case CodeBinaryOperatorType.Modulus:
                literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                if (literal3 == null)
                {
                    break;
                }
                literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                if (literal4 == null)
                {
                    break;
                }
                return(literal3.Modulus(literal4));

            case CodeBinaryOperatorType.IdentityInequality:
                return(lhsValue != rhsValue);

            case CodeBinaryOperatorType.IdentityEquality:
                return(lhsValue == rhsValue);

            case CodeBinaryOperatorType.ValueEquality:
                literal = Literal.MakeLiteral(lhsType, lhsValue);
                if (literal == null)
                {
                    break;
                }
                literal2 = Literal.MakeLiteral(rhsType, rhsValue);
                if (literal2 == null)
                {
                    break;
                }
                return(literal.Equal(literal2));

            case CodeBinaryOperatorType.BitwiseOr:
                literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                if (literal3 == null)
                {
                    break;
                }
                literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                if (literal4 == null)
                {
                    break;
                }
                return(literal3.BitOr(literal4));

            case CodeBinaryOperatorType.BitwiseAnd:
                literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                if (literal3 == null)
                {
                    break;
                }
                literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                if (literal4 == null)
                {
                    break;
                }
                return(literal3.BitAnd(literal4));

            case CodeBinaryOperatorType.LessThan:
                literal = Literal.MakeLiteral(lhsType, lhsValue);
                if (literal == null)
                {
                    break;
                }
                literal2 = Literal.MakeLiteral(rhsType, rhsValue);
                if (literal2 == null)
                {
                    break;
                }
                return(literal.LessThan(literal2));

            case CodeBinaryOperatorType.LessThanOrEqual:
                literal = Literal.MakeLiteral(lhsType, lhsValue);
                if (literal == null)
                {
                    break;
                }
                literal2 = Literal.MakeLiteral(rhsType, rhsValue);
                if (literal2 == null)
                {
                    break;
                }
                return(literal.LessThanOrEqual(literal2));

            case CodeBinaryOperatorType.GreaterThan:
                literal = Literal.MakeLiteral(lhsType, lhsValue);
                if (literal == null)
                {
                    break;
                }
                literal2 = Literal.MakeLiteral(rhsType, rhsValue);
                if (literal2 == null)
                {
                    break;
                }
                return(literal.GreaterThan(literal2));

            case CodeBinaryOperatorType.GreaterThanOrEqual:
                literal = Literal.MakeLiteral(lhsType, lhsValue);
                if (literal == null)
                {
                    break;
                }
                literal2 = Literal.MakeLiteral(rhsType, rhsValue);
                if (literal2 == null)
                {
                    break;
                }
                return(literal.GreaterThanOrEqual(literal2));

            default:
                exception = new RuleEvaluationException(string.Format(CultureInfo.CurrentCulture, Messages.BinaryOpNotSupported, new object[] { operation.ToString() }));
                exception.Data["ErrorObject"] = binaryExpr;
                throw exception;
            }
            exception = new RuleEvaluationException(string.Format(CultureInfo.CurrentCulture, Messages.BinaryOpFails, new object[] { operation.ToString(), RuleDecompiler.DecompileType(lhsType), RuleDecompiler.DecompileType(rhsType) }));
            exception.Data["ErrorObject"] = binaryExpr;
            throw exception;
        }
コード例 #3
0
 private static void dumpExpression(CodeExpression e)
 {
     /*
      *               System.CodeDom.CodeArgumentReferenceExpression
      *                 System.CodeDom.CodeArrayCreateExpression
      *                 System.CodeDom.CodeArrayIndexerExpression
      *                 System.CodeDom.CodeBaseReferenceExpression
      *                 System.CodeDom.CodeBinaryOperatorExpression
      *                 System.CodeDom.CodeCastExpression
      *                 System.CodeDom.CodeDefaultValueExpression
      *                 System.CodeDom.CodeDelegateCreateExpression
      *                 System.CodeDom.CodeDelegateInvokeExpression
      *                 System.CodeDom.CodeDirectionExpression
      *                 System.CodeDom.CodeEventReferenceExpression
      *                 System.CodeDom.CodeFieldReferenceExpression
      *                 System.CodeDom.CodeIndexerExpression
      *                 System.CodeDom.CodeMethodInvokeExpression
      *                 System.CodeDom.CodeMethodReferenceExpression
      *                 System.CodeDom.CodeObjectCreateExpression
      *                 System.CodeDom.CodeParameterDeclarationExpression
      *                 System.CodeDom.CodePrimitiveExpression
      *                 System.CodeDom.CodePropertyReferenceExpression
      *                 System.CodeDom.CodePropertySetValueReferenceExpression
      *                 System.CodeDom.CodeSnippetExpression
      *                 System.CodeDom.CodeThisReferenceExpression
      *                 System.CodeDom.CodeTypeOfExpression
      *                 System.CodeDom.CodeTypeReferenceExpression
      *                 System.CodeDom.CodeVariableReferenceExpression
      */
     if (e == null)
     {
         return;
     }
     if (e is CodeFieldReferenceExpression)
     {
         CodeFieldReferenceExpression exp = (CodeFieldReferenceExpression)e;
         dumpExpression(exp.TargetObject);
         writeLineIndent("F: " + exp.FieldName);
     }
     else if (e is CodeObjectCreateExpression)
     {
         var exp = (CodeObjectCreateExpression)e;
         var tr  = exp.CreateType as CodeTypeReference;
         writeLineIndent(tr.BaseType + "{}");
         dumpExpressionList(exp.Parameters);
     }
     else if (e is CodeMethodInvokeExpression)
     {
         var exp = (CodeMethodInvokeExpression)e;
         dumpExpression(exp.Method.TargetObject);
         writeLineIndent("M: " + exp.Method.MethodName);
         dumpExpressionList(exp.Parameters);
     }
     else if (e is CodePropertyReferenceExpression)
     {
         var exp = (CodePropertyReferenceExpression)e;
         dumpExpression(exp.TargetObject);
         writeLineIndent("P: " + exp.PropertyName);
     }
     else if (e is CodePrimitiveExpression)
     {
         var exp = (CodePrimitiveExpression)e;
         writeLineIndent(exp.ToString());
         writeLineIndent(exp.Value.ToString());
     }
     else if (e is CodeCastExpression)
     {
         var exp = (CodeCastExpression)e;
         writeLineIndent(exp.TargetType.ToString());
         dumpExpression(exp.Expression);
     }
     else if (e is CodeThisReferenceExpression)
     {
         writeLineIndent("SELF");
     }
     else if (e is CodeBinaryOperatorExpression)
     {
         var exp = (CodeBinaryOperatorExpression)e;
         dumpExpression(exp.Left);
         CodeBinaryOperatorType opType = exp.Operator;
         writeLineIndent(opType.ToString());
         dumpExpression(exp.Right);
     }
     else if (e is CodeTypeReferenceExpression)
     {
         var exp = (CodeTypeReferenceExpression)e;
         var tr  = exp.Type;
         writeLineIndent(tr.BaseType);
     }
     else if (e is CodeBaseReferenceExpression)
     {
         writeLineIndent("SUPER");
     }
     else
     {
         writeLineIndent(e.GetType().FullName);
     }
 }
コード例 #4
0
        internal static RuleBinaryExpressionInfo AllowedComparison(
            Type lhs,
            CodeExpression lhsExpression,
            Type rhs,
            CodeExpression rhsExpression,
            CodeBinaryOperatorType comparison,
            RuleValidation validator,
            out ValidationError error)
        {
            // note that null values come in as a NullLiteral type
            TypeFlags lhsFlags, rhsFlags;

            // are the types supported?
            if ((supportedTypes.TryGetValue(lhs, out lhsFlags)) && (supportedTypes.TryGetValue(rhs, out rhsFlags)))
            {
                // both sides supported
                if (lhsFlags == rhsFlags)
                {
                    // both sides the same type, so it's allowed
                    // only allow equality on booleans
                    if ((lhsFlags == TypeFlags.Bool) && (comparison != CodeBinaryOperatorType.ValueEquality))
                    {
                        string message = string.Format(CultureInfo.CurrentCulture, Messages.RelationalOpBadTypes, comparison.ToString(),
                            RuleDecompiler.DecompileType(lhs),
                            RuleDecompiler.DecompileType(rhs));
                        error = new ValidationError(message, ErrorNumbers.Error_OperandTypesIncompatible);
                        return null;
                    }
                    error = null;
                    return new RuleBinaryExpressionInfo(lhs, rhs, typeof(bool));
                }

                // if not the same, only certain combinations allowed
                switch (lhsFlags | rhsFlags)
                {
                    case TypeFlags.Decimal | TypeFlags.SignedNumbers:
                    case TypeFlags.Decimal | TypeFlags.UnsignedNumbers:
                    case TypeFlags.Decimal | TypeFlags.ULong:
                    case TypeFlags.Float | TypeFlags.SignedNumbers:
                    case TypeFlags.Float | TypeFlags.UnsignedNumbers:
                    case TypeFlags.Float | TypeFlags.ULong:
                    case TypeFlags.ULong | TypeFlags.UnsignedNumbers:
                    case TypeFlags.SignedNumbers | TypeFlags.UnsignedNumbers:
                        error = null;
                        return new RuleBinaryExpressionInfo(lhs, rhs, typeof(bool));
                }
                string message2 = string.Format(CultureInfo.CurrentCulture, Messages.RelationalOpBadTypes, comparison.ToString(),
                    (lhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(lhs),
                    (rhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(rhs));
                error = new ValidationError(message2, ErrorNumbers.Error_OperandTypesIncompatible);
                return null;
            }
            else
            {
                // see if they override the operator
                MethodInfo operatorOverride = MapOperatorToMethod(comparison, lhs, lhsExpression, rhs, rhsExpression, validator, out error);
                if (operatorOverride != null)
                    return new RuleBinaryExpressionInfo(lhs, rhs, operatorOverride);

                // unable to evaluate, so return false
                return null;
            }
        }
コード例 #5
0
        [SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]     // bogus since the casts are in different case statements
        internal static MethodInfo MapOperatorToMethod(
            CodeBinaryOperatorType op,
            Type lhs,
            CodeExpression lhsExpression,
            Type rhs,
            CodeExpression rhsExpression,
            RuleValidation validator,
            out ValidationError error)
        {
            // determine what the method name should be
            string methodName;
            string message;
            OperatorGrouping group;

            switch (op)
            {
                case CodeBinaryOperatorType.ValueEquality:
                    methodName = "op_Equality";
                    group = OperatorGrouping.Equality;
                    break;
                case CodeBinaryOperatorType.GreaterThan:
                    methodName = "op_GreaterThan";
                    group = OperatorGrouping.Relational;
                    break;
                case CodeBinaryOperatorType.GreaterThanOrEqual:
                    methodName = "op_GreaterThanOrEqual";
                    group = OperatorGrouping.Relational;
                    break;
                case CodeBinaryOperatorType.LessThan:
                    methodName = "op_LessThan";
                    group = OperatorGrouping.Relational;
                    break;
                case CodeBinaryOperatorType.LessThanOrEqual:
                    methodName = "op_LessThanOrEqual";
                    group = OperatorGrouping.Relational;
                    break;
                case CodeBinaryOperatorType.Add:
                    methodName = "op_Addition";
                    group = OperatorGrouping.Arithmetic;
                    break;
                case CodeBinaryOperatorType.Subtract:
                    methodName = "op_Subtraction";
                    group = OperatorGrouping.Arithmetic;
                    break;
                case CodeBinaryOperatorType.Multiply:
                    methodName = "op_Multiply";
                    group = OperatorGrouping.Arithmetic;
                    break;
                case CodeBinaryOperatorType.Divide:
                    methodName = "op_Division";
                    group = OperatorGrouping.Arithmetic;
                    break;
                case CodeBinaryOperatorType.Modulus:
                    methodName = "op_Modulus";
                    group = OperatorGrouping.Arithmetic;
                    break;
                case CodeBinaryOperatorType.BitwiseAnd:
                    methodName = "op_BitwiseAnd";
                    group = OperatorGrouping.Arithmetic;
                    break;
                case CodeBinaryOperatorType.BitwiseOr:
                    methodName = "op_BitwiseOr";
                    group = OperatorGrouping.Arithmetic;
                    break;
                default:
                    Debug.Assert(false, "Operator " + op.ToString() + " not implemented");
                    message = string.Format(CultureInfo.CurrentCulture, Messages.BinaryOpNotSupported, op.ToString());
                    error = new ValidationError(message, ErrorNumbers.Error_CodeExpressionNotHandled);
                    return null;
            }

            // NOTE: types maybe NullLiteral, which signifies the constant "null"
            List<MethodInfo> candidates = new List<MethodInfo>();
            bool lhsNullable = ConditionHelper.IsNullableValueType(lhs);
            bool rhsNullable = ConditionHelper.IsNullableValueType(rhs);
            Type lhsType0 = (lhsNullable) ? Nullable.GetUnderlyingType(lhs) : lhs;
            Type rhsType0 = (rhsNullable) ? Nullable.GetUnderlyingType(rhs) : rhs;

            // special cases for enums
            if (lhsType0.IsEnum)
            {
                // only 3 cases (U = underlying type of E):
                //    E = E + U
                //    U = E - E
                //    E = E - U
                // plus the standard comparisons (E == E, E > E, etc.)
                // need to also allow E == 0
                Type underlyingType;
                switch (op)
                {
                    case CodeBinaryOperatorType.Add:
                        underlyingType = EnumHelper.GetUnderlyingType(lhsType0);
                        if ((underlyingType != null) &&
                            (RuleValidation.TypesAreAssignable(rhsType0, underlyingType, rhsExpression, out error)))
                        {
                            error = null;
                            return new EnumOperationMethodInfo(lhs, op, rhs, false);
                        }
                        break;
                    case CodeBinaryOperatorType.Subtract:
                        underlyingType = EnumHelper.GetUnderlyingType(lhsType0);
                        if (underlyingType != null)
                        {
                            if (lhsType0 == rhsType0)
                            {
                                // E - E
                                error = null;
                                return new EnumOperationMethodInfo(lhs, op, rhs, false);
                            }
                            else if (DecimalIntegerLiteralZero(rhs, rhsExpression as CodePrimitiveExpression))
                            {
                                // E - 0, can convert 0 to E
                                error = null;
                                return new EnumOperationMethodInfo(lhs, op, rhs, true);
                            }
                            else if (RuleValidation.TypesAreAssignable(rhsType0, underlyingType, rhsExpression, out error))
                            {
                                // expression not passed to TypesAreAssignable, so not looking for constants (since 0 is all we care about)
                                error = null;
                                return new EnumOperationMethodInfo(lhs, op, rhs, false);
                            }
                        }
                        break;
                    case CodeBinaryOperatorType.ValueEquality:
                    case CodeBinaryOperatorType.LessThan:
                    case CodeBinaryOperatorType.LessThanOrEqual:
                    case CodeBinaryOperatorType.GreaterThan:
                    case CodeBinaryOperatorType.GreaterThanOrEqual:
                        if (lhsType0 == rhsType0)
                        {
                            error = null;
                            return new EnumOperationMethodInfo(lhs, op, rhs, false);
                        }
                        else if (lhsNullable && (rhs == typeof(NullLiteral)))
                        {
                            // handle enum? op null
                            // treat the rhs as the same nullable enum
                            error = null;
                            return new EnumOperationMethodInfo(lhs, op, lhs, false);
                        }
                        else if (DecimalIntegerLiteralZero(rhs, rhsExpression as CodePrimitiveExpression))
                        {
                            error = null;
                            return new EnumOperationMethodInfo(lhs, op, rhs, true);
                        }
                        break;
                }
                // can't do it, sorry
                // but check if there is a user-defined operator that works
            }
            else if (rhsType0.IsEnum)
            {
                // lhs != enum, so only 2 cases (U = underlying type of E):
                //    E = U + E
                //    E = U - E
                // comparisons are E == E, etc., so if the lhs is not an enum, too bad
                // although we need to check for 0 == E
                Type underlyingType;
                switch (op)
                {
                    case CodeBinaryOperatorType.Add:
                        underlyingType = EnumHelper.GetUnderlyingType(rhsType0);
                        if ((underlyingType != null) &&
                            (RuleValidation.TypesAreAssignable(lhsType0, underlyingType, lhsExpression, out error)))
                        {
                            error = null;
                            return new EnumOperationMethodInfo(lhs, op, rhs, false);
                        }
                        break;

                    case CodeBinaryOperatorType.Subtract:
                        underlyingType = EnumHelper.GetUnderlyingType(rhsType0);
                        if (underlyingType != null)
                        {
                            CodePrimitiveExpression primitive = lhsExpression as CodePrimitiveExpression;
                            if (DecimalIntegerLiteralZero(lhs, primitive))
                            {
                                // 0 - E, can convert 0 to E
                                error = null;
                                return new EnumOperationMethodInfo(lhs, op, rhs, true);
                            }
                            else if (RuleValidation.TypesAreAssignable(lhsType0, underlyingType, lhsExpression, out error))
                            {
                                // expression not passed to TypesAreAssignable, so not looking for constants (since 0 is all we care about)
                                error = null;
                                return new EnumOperationMethodInfo(lhs, op, rhs, false);
                            }
                        }
                        break;

                    case CodeBinaryOperatorType.ValueEquality:
                    case CodeBinaryOperatorType.LessThan:
                    case CodeBinaryOperatorType.LessThanOrEqual:
                    case CodeBinaryOperatorType.GreaterThan:
                    case CodeBinaryOperatorType.GreaterThanOrEqual:
                        if (rhsNullable && (lhs == typeof(NullLiteral)))
                        {
                            // handle null op enum?
                            // treat the lhs as the same nullable enum type
                            error = null;
                            return new EnumOperationMethodInfo(rhs, op, rhs, false);
                        }
                        else if (DecimalIntegerLiteralZero(lhs, lhsExpression as CodePrimitiveExpression))
                        {
                            error = null;
                            return new EnumOperationMethodInfo(lhs, op, rhs, true);
                        }
                        break;
                }

                // can't do it, sorry
                // but check if there is a user-defined operator that works
            }

            // enum specific operations already handled, see if one side (or both) define operators
            AddOperatorOverloads(lhsType0, methodName, lhs, rhs, candidates);
            AddOperatorOverloads(rhsType0, methodName, lhs, rhs, candidates);
            if (lhsNullable || rhsNullable || (lhs == typeof(NullLiteral)) || (rhs == typeof(NullLiteral)))
            {
                // need to add in lifted methods
                AddLiftedOperators(lhsType0, methodName, group, lhsType0, rhsType0, candidates);
                AddLiftedOperators(rhsType0, methodName, group, lhsType0, rhsType0, candidates);
            }

            if (candidates.Count == 0)
            {
                // no overrides, so get the default list
                methodName = methodName.Substring(3);       // strip off the op_
                foreach (MethodInfo mi in typeof(DefaultOperators).GetMethods())
                {
                    if (mi.Name == methodName)
                    {
                        ParameterInfo[] parameters = mi.GetParameters();
                        Type parm1 = parameters[0].ParameterType;
                        Type parm2 = parameters[1].ParameterType;
                        if (RuleValidation.ImplicitConversion(lhs, parm1) &&
                            RuleValidation.ImplicitConversion(rhs, parm2))
                        {
                            candidates.Add(mi);
                        }
                    }
                }

                // if no candidates and ==, can we use object == object?
                if ((candidates.Count == 0) && ("Equality" == methodName))
                {
                    // C# 7.9.6
                    // references must be compatible
                    // no boxing
                    // value types can't be compared
                    if ((!lhs.IsValueType) && (!rhs.IsValueType))
                    {
                        // they are not classes, so references need to be compatible
                        // also check for null (which is NullLiteral type) -- null is compatible with any object type
                        if ((lhs == typeof(NullLiteral)) || (rhs == typeof(NullLiteral)) ||
                            (lhs.IsAssignableFrom(rhs)) || (rhs.IsAssignableFrom(lhs)))
                        {
                            candidates.Add(ObjectEquality);
                        }
                    }
                }

                // if no candidates and nullable, add lifted operators
                if ((candidates.Count == 0) && ((lhsNullable || rhsNullable || (lhs == typeof(NullLiteral)) || (rhs == typeof(NullLiteral)))))
                {
                    foreach (MethodInfo mi in typeof(DefaultOperators).GetMethods())
                    {
                        if (mi.Name == methodName)
                        {
                            ParameterInfo[] parameters = mi.GetParameters();
                            MethodInfo liftedMethod = EvaluateLiftedMethod(mi, parameters, group, lhsType0, rhsType0);
                            if (liftedMethod != null)
                                candidates.Add(liftedMethod);
                        }
                    }
                }
            }
            if (candidates.Count == 1)
            {
                // only 1, so it is it
                error = null;
                return candidates[0];
            }
            else if (candidates.Count == 0)
            {
                // nothing matched
                message = string.Format(CultureInfo.CurrentCulture,
                    (group == OperatorGrouping.Arithmetic) ? Messages.ArithOpBadTypes : Messages.RelationalOpBadTypes,
                    op.ToString(),
                    (lhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(lhs),
                    (rhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(rhs));
                error = new ValidationError(message, ErrorNumbers.Error_OperandTypesIncompatible);
                return null;
            }
            else
            {
                // more than 1, so pick the best one
                MethodInfo bestFit = validator.FindBestCandidate(null, candidates, lhs, rhs);
                if (bestFit != null)
                {
                    error = null;
                    return bestFit;
                }
                // must be ambiguous. Since there are at least 2 choices, show only the first 2
                message = string.Format(CultureInfo.CurrentCulture,
                    Messages.AmbiguousOperator,
                    op.ToString(),
                    RuleDecompiler.DecompileMethod(candidates[0]),
                    RuleDecompiler.DecompileMethod(candidates[1]));
                error = new ValidationError(message, ErrorNumbers.Error_OperandTypesIncompatible);
                return null;
            }
        }
コード例 #6
0
        internal static RuleBinaryExpressionInfo ResultType(CodeBinaryOperatorType operation, Type lhs, CodeExpression lhsExpression, Type rhs, CodeExpression rhsExpression, RuleValidation validator, out ValidationError error)
        {
            TypeFlags flags;
            TypeFlags flags2;

            if (supportedTypes.TryGetValue(lhs, out flags) && supportedTypes.TryGetValue(rhs, out flags2))
            {
                Type resultType = ResultType(operation, flags, flags2);
                if (resultType != null)
                {
                    error = null;
                    return(new RuleBinaryExpressionInfo(lhs, rhs, resultType));
                }
                string errorText = string.Format(CultureInfo.CurrentCulture, Messages.ArithOpBadTypes, new object[] { operation.ToString(), (lhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(lhs), (rhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(rhs) });
                error = new ValidationError(errorText, 0x545);
                return(null);
            }
            MethodInfo mi = Literal.MapOperatorToMethod(operation, lhs, lhsExpression, rhs, rhsExpression, validator, out error);

            if (mi != null)
            {
                return(new RuleBinaryExpressionInfo(lhs, rhs, mi));
            }
            return(null);
        }
        private static object EvaluateBinaryOperation(CodeBinaryOperatorExpression binaryExpr, Type lhsType, object lhsValue, CodeBinaryOperatorType operation, Type rhsType, object rhsValue)
        {
            Literal literal;
            Literal literal2;
            ArithmeticLiteral literal3;
            ArithmeticLiteral literal4;
            RuleEvaluationException exception;
            switch (operation)
            {
                case CodeBinaryOperatorType.Add:
                    literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (literal3 == null)
                    {
                        break;
                    }
                    literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (literal4 == null)
                    {
                        break;
                    }
                    return literal3.Add(literal4);

                case CodeBinaryOperatorType.Subtract:
                    literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (literal3 == null)
                    {
                        break;
                    }
                    literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (literal4 == null)
                    {
                        break;
                    }
                    return literal3.Subtract(literal4);

                case CodeBinaryOperatorType.Multiply:
                    literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (literal3 == null)
                    {
                        break;
                    }
                    literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (literal4 == null)
                    {
                        break;
                    }
                    return literal3.Multiply(literal4);

                case CodeBinaryOperatorType.Divide:
                    literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (literal3 == null)
                    {
                        break;
                    }
                    literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (literal4 == null)
                    {
                        break;
                    }
                    return literal3.Divide(literal4);

                case CodeBinaryOperatorType.Modulus:
                    literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (literal3 == null)
                    {
                        break;
                    }
                    literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (literal4 == null)
                    {
                        break;
                    }
                    return literal3.Modulus(literal4);

                case CodeBinaryOperatorType.IdentityInequality:
                    return (lhsValue != rhsValue);

                case CodeBinaryOperatorType.IdentityEquality:
                    return (lhsValue == rhsValue);

                case CodeBinaryOperatorType.ValueEquality:
                    literal = Literal.MakeLiteral(lhsType, lhsValue);
                    if (literal == null)
                    {
                        break;
                    }
                    literal2 = Literal.MakeLiteral(rhsType, rhsValue);
                    if (literal2 == null)
                    {
                        break;
                    }
                    return literal.Equal(literal2);

                case CodeBinaryOperatorType.BitwiseOr:
                    literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (literal3 == null)
                    {
                        break;
                    }
                    literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (literal4 == null)
                    {
                        break;
                    }
                    return literal3.BitOr(literal4);

                case CodeBinaryOperatorType.BitwiseAnd:
                    literal3 = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (literal3 == null)
                    {
                        break;
                    }
                    literal4 = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (literal4 == null)
                    {
                        break;
                    }
                    return literal3.BitAnd(literal4);

                case CodeBinaryOperatorType.LessThan:
                    literal = Literal.MakeLiteral(lhsType, lhsValue);
                    if (literal == null)
                    {
                        break;
                    }
                    literal2 = Literal.MakeLiteral(rhsType, rhsValue);
                    if (literal2 == null)
                    {
                        break;
                    }
                    return literal.LessThan(literal2);

                case CodeBinaryOperatorType.LessThanOrEqual:
                    literal = Literal.MakeLiteral(lhsType, lhsValue);
                    if (literal == null)
                    {
                        break;
                    }
                    literal2 = Literal.MakeLiteral(rhsType, rhsValue);
                    if (literal2 == null)
                    {
                        break;
                    }
                    return literal.LessThanOrEqual(literal2);

                case CodeBinaryOperatorType.GreaterThan:
                    literal = Literal.MakeLiteral(lhsType, lhsValue);
                    if (literal == null)
                    {
                        break;
                    }
                    literal2 = Literal.MakeLiteral(rhsType, rhsValue);
                    if (literal2 == null)
                    {
                        break;
                    }
                    return literal.GreaterThan(literal2);

                case CodeBinaryOperatorType.GreaterThanOrEqual:
                    literal = Literal.MakeLiteral(lhsType, lhsValue);
                    if (literal == null)
                    {
                        break;
                    }
                    literal2 = Literal.MakeLiteral(rhsType, rhsValue);
                    if (literal2 == null)
                    {
                        break;
                    }
                    return literal.GreaterThanOrEqual(literal2);

                default:
                    exception = new RuleEvaluationException(string.Format(CultureInfo.CurrentCulture, Messages.BinaryOpNotSupported, new object[] { operation.ToString() }));
                    exception.Data["ErrorObject"] = binaryExpr;
                    throw exception;
            }
            exception = new RuleEvaluationException(string.Format(CultureInfo.CurrentCulture, Messages.BinaryOpFails, new object[] { operation.ToString(), RuleDecompiler.DecompileType(lhsType), RuleDecompiler.DecompileType(rhsType) }));
            exception.Data["ErrorObject"] = binaryExpr;
            throw exception;
        }
コード例 #8
0
 private NodeType Translate(CodeBinaryOperatorType oper){
   switch(oper){
     case CodeBinaryOperatorType.Add : return NodeType.Add;
     case CodeBinaryOperatorType.BitwiseAnd : return NodeType.And;
     case CodeBinaryOperatorType.BitwiseOr : return NodeType.Or;
     case CodeBinaryOperatorType.BooleanAnd : return NodeType.LogicalAnd;
     case CodeBinaryOperatorType.BooleanOr : return NodeType.LogicalOr;
     case CodeBinaryOperatorType.Divide : return NodeType.Div;
     case CodeBinaryOperatorType.GreaterThan : return NodeType.Gt;
     case CodeBinaryOperatorType.GreaterThanOrEqual : return NodeType.Ge;
     case CodeBinaryOperatorType.IdentityEquality: return NodeType.Eq;
     case CodeBinaryOperatorType.IdentityInequality: return NodeType.Ne;
     case CodeBinaryOperatorType.LessThan : return NodeType.Lt;
     case CodeBinaryOperatorType.LessThanOrEqual : return NodeType.Le;
     case CodeBinaryOperatorType.Modulus : return NodeType.Rem;
     case CodeBinaryOperatorType.Multiply : return NodeType.Mul;
     case CodeBinaryOperatorType.Subtract : return NodeType.Sub;
     case CodeBinaryOperatorType.ValueEquality : return NodeType.Eq;
   }
   Debug.Assert(false);
   this.HandleError(Error.DidNotExpect, "CodeBinaryOperatorType value == "+oper.ToString());
   return NodeType.Nop;
 }
コード例 #9
0
 internal static RuleBinaryExpressionInfo ResultType(
     CodeBinaryOperatorType operation,
     Type lhs,
     CodeExpression lhsExpression,
     Type rhs,
     CodeExpression rhsExpression,
     RuleValidation validator,
     out ValidationError error)
 {
     // do we support the types natively?
     TypeFlags lhsType, rhsType;
     if (supportedTypes.TryGetValue(lhs, out lhsType) && supportedTypes.TryGetValue(rhs, out rhsType))
     {
         Type resultType = ResultType(operation, lhsType, rhsType);
         if (resultType != null)
         {
             error = null;
             return new RuleBinaryExpressionInfo(lhs, rhs, resultType);
         }
         else
         {
             string message = string.Format(CultureInfo.CurrentCulture, Messages.ArithOpBadTypes, operation.ToString(),
                 (lhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(lhs),
                 (rhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(rhs));
             error = new ValidationError(message, ErrorNumbers.Error_OperandTypesIncompatible);
             return null;
         }
     }
     else
     {
         // not natively supported, see if user overrides operator
         MethodInfo opOverload = Literal.MapOperatorToMethod(operation, lhs, lhsExpression, rhs, rhsExpression, validator, out error);
         if (opOverload != null)
             return new RuleBinaryExpressionInfo(lhs, rhs, opOverload);
         else
             return null;
     }
 }
コード例 #10
0
 internal static RuleBinaryExpressionInfo AllowedComparison(Type lhs, CodeExpression lhsExpression, Type rhs, CodeExpression rhsExpression, CodeBinaryOperatorType comparison, RuleValidation validator, out ValidationError error)
 {
     TypeFlags flags;
     TypeFlags flags2;
     if (!supportedTypes.TryGetValue(lhs, out flags) || !supportedTypes.TryGetValue(rhs, out flags2))
     {
         MethodInfo mi = MapOperatorToMethod(comparison, lhs, lhsExpression, rhs, rhsExpression, validator, out error);
         if (mi != null)
         {
             return new RuleBinaryExpressionInfo(lhs, rhs, mi);
         }
         return null;
     }
     if (flags == flags2)
     {
         if ((flags == TypeFlags.Bool) && (comparison != CodeBinaryOperatorType.ValueEquality))
         {
             string str = string.Format(CultureInfo.CurrentCulture, Messages.RelationalOpBadTypes, new object[] { comparison.ToString(), RuleDecompiler.DecompileType(lhs), RuleDecompiler.DecompileType(rhs) });
             error = new ValidationError(str, 0x545);
             return null;
         }
         error = null;
         return new RuleBinaryExpressionInfo(lhs, rhs, typeof(bool));
     }
     switch ((flags | flags2))
     {
         case (TypeFlags.ULong | TypeFlags.UnsignedNumbers):
         case (TypeFlags.Float | TypeFlags.SignedNumbers):
         case (TypeFlags.Float | TypeFlags.UnsignedNumbers):
         case (TypeFlags.Float | TypeFlags.ULong):
         case (TypeFlags.UnsignedNumbers | TypeFlags.SignedNumbers):
         case (TypeFlags.Decimal | TypeFlags.SignedNumbers):
         case (TypeFlags.Decimal | TypeFlags.UnsignedNumbers):
         case (TypeFlags.Decimal | TypeFlags.ULong):
             error = null;
             return new RuleBinaryExpressionInfo(lhs, rhs, typeof(bool));
     }
     string errorText = string.Format(CultureInfo.CurrentCulture, Messages.RelationalOpBadTypes, new object[] { comparison.ToString(), (lhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(lhs), (rhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(rhs) });
     error = new ValidationError(errorText, 0x545);
     return null;
 }
コード例 #11
0
        internal static MethodInfo MapOperatorToMethod(CodeBinaryOperatorType op, Type lhs, CodeExpression lhsExpression, Type rhs, CodeExpression rhsExpression, RuleValidation validator, out ValidationError error)
        {
            string str;
            string str2;
            OperatorGrouping arithmetic;
            switch (op)
            {
                case CodeBinaryOperatorType.Add:
                    str = "op_Addition";
                    arithmetic = OperatorGrouping.Arithmetic;
                    break;

                case CodeBinaryOperatorType.Subtract:
                    str = "op_Subtraction";
                    arithmetic = OperatorGrouping.Arithmetic;
                    break;

                case CodeBinaryOperatorType.Multiply:
                    str = "op_Multiply";
                    arithmetic = OperatorGrouping.Arithmetic;
                    break;

                case CodeBinaryOperatorType.Divide:
                    str = "op_Division";
                    arithmetic = OperatorGrouping.Arithmetic;
                    break;

                case CodeBinaryOperatorType.Modulus:
                    str = "op_Modulus";
                    arithmetic = OperatorGrouping.Arithmetic;
                    break;

                case CodeBinaryOperatorType.ValueEquality:
                    str = "op_Equality";
                    arithmetic = OperatorGrouping.Equality;
                    break;

                case CodeBinaryOperatorType.BitwiseOr:
                    str = "op_BitwiseOr";
                    arithmetic = OperatorGrouping.Arithmetic;
                    break;

                case CodeBinaryOperatorType.BitwiseAnd:
                    str = "op_BitwiseAnd";
                    arithmetic = OperatorGrouping.Arithmetic;
                    break;

                case CodeBinaryOperatorType.LessThan:
                    str = "op_LessThan";
                    arithmetic = OperatorGrouping.Relational;
                    break;

                case CodeBinaryOperatorType.LessThanOrEqual:
                    str = "op_LessThanOrEqual";
                    arithmetic = OperatorGrouping.Relational;
                    break;

                case CodeBinaryOperatorType.GreaterThan:
                    str = "op_GreaterThan";
                    arithmetic = OperatorGrouping.Relational;
                    break;

                case CodeBinaryOperatorType.GreaterThanOrEqual:
                    str = "op_GreaterThanOrEqual";
                    arithmetic = OperatorGrouping.Relational;
                    break;

                default:
                    str2 = string.Format(CultureInfo.CurrentCulture, Messages.BinaryOpNotSupported, new object[] { op.ToString() });
                    error = new ValidationError(str2, 0x548);
                    return null;
            }
            List<MethodInfo> candidates = new List<MethodInfo>();
            bool flag = ConditionHelper.IsNullableValueType(lhs);
            bool flag2 = ConditionHelper.IsNullableValueType(rhs);
            Type rhsType = flag ? Nullable.GetUnderlyingType(lhs) : lhs;
            Type type = flag2 ? Nullable.GetUnderlyingType(rhs) : rhs;
            if (!rhsType.IsEnum)
            {
                if (type.IsEnum)
                {
                    Type underlyingType;
                    switch (op)
                    {
                        case CodeBinaryOperatorType.Add:
                            underlyingType = EnumHelper.GetUnderlyingType(type);
                            if ((underlyingType == null) || !RuleValidation.TypesAreAssignable(rhsType, underlyingType, lhsExpression, out error))
                            {
                                break;
                            }
                            error = null;
                            return new EnumOperationMethodInfo(lhs, op, rhs, false);

                        case CodeBinaryOperatorType.Subtract:
                        {
                            underlyingType = EnumHelper.GetUnderlyingType(type);
                            if (underlyingType == null)
                            {
                                break;
                            }
                            CodePrimitiveExpression expression = lhsExpression as CodePrimitiveExpression;
                            if (!DecimalIntegerLiteralZero(lhs, expression))
                            {
                                if (!RuleValidation.TypesAreAssignable(rhsType, underlyingType, lhsExpression, out error))
                                {
                                    break;
                                }
                                error = null;
                                return new EnumOperationMethodInfo(lhs, op, rhs, false);
                            }
                            error = null;
                            return new EnumOperationMethodInfo(lhs, op, rhs, true);
                        }
                        case CodeBinaryOperatorType.ValueEquality:
                        case CodeBinaryOperatorType.LessThan:
                        case CodeBinaryOperatorType.LessThanOrEqual:
                        case CodeBinaryOperatorType.GreaterThan:
                        case CodeBinaryOperatorType.GreaterThanOrEqual:
                            if (!flag2 || !(lhs == typeof(NullLiteral)))
                            {
                                if (DecimalIntegerLiteralZero(lhs, lhsExpression as CodePrimitiveExpression))
                                {
                                    error = null;
                                    return new EnumOperationMethodInfo(lhs, op, rhs, true);
                                }
                                break;
                            }
                            error = null;
                            return new EnumOperationMethodInfo(rhs, op, rhs, false);
                    }
                }
            }
            else
            {
                Type type3;
                switch (op)
                {
                    case CodeBinaryOperatorType.Add:
                        type3 = EnumHelper.GetUnderlyingType(rhsType);
                        if ((type3 == null) || !RuleValidation.TypesAreAssignable(type, type3, rhsExpression, out error))
                        {
                            break;
                        }
                        error = null;
                        return new EnumOperationMethodInfo(lhs, op, rhs, false);

                    case CodeBinaryOperatorType.Subtract:
                        type3 = EnumHelper.GetUnderlyingType(rhsType);
                        if (type3 == null)
                        {
                            break;
                        }
                        if (!(rhsType == type))
                        {
                            if (DecimalIntegerLiteralZero(rhs, rhsExpression as CodePrimitiveExpression))
                            {
                                error = null;
                                return new EnumOperationMethodInfo(lhs, op, rhs, true);
                            }
                            if (!RuleValidation.TypesAreAssignable(type, type3, rhsExpression, out error))
                            {
                                break;
                            }
                            error = null;
                            return new EnumOperationMethodInfo(lhs, op, rhs, false);
                        }
                        error = null;
                        return new EnumOperationMethodInfo(lhs, op, rhs, false);

                    case CodeBinaryOperatorType.ValueEquality:
                    case CodeBinaryOperatorType.LessThan:
                    case CodeBinaryOperatorType.LessThanOrEqual:
                    case CodeBinaryOperatorType.GreaterThan:
                    case CodeBinaryOperatorType.GreaterThanOrEqual:
                        if (!(rhsType == type))
                        {
                            if (flag && (rhs == typeof(NullLiteral)))
                            {
                                error = null;
                                return new EnumOperationMethodInfo(lhs, op, lhs, false);
                            }
                            if (!DecimalIntegerLiteralZero(rhs, rhsExpression as CodePrimitiveExpression))
                            {
                                break;
                            }
                            error = null;
                            return new EnumOperationMethodInfo(lhs, op, rhs, true);
                        }
                        error = null;
                        return new EnumOperationMethodInfo(lhs, op, rhs, false);
                }
            }
            AddOperatorOverloads(rhsType, str, lhs, rhs, candidates);
            AddOperatorOverloads(type, str, lhs, rhs, candidates);
            if ((flag || flag2) || ((lhs == typeof(NullLiteral)) || (rhs == typeof(NullLiteral))))
            {
                AddLiftedOperators(rhsType, str, arithmetic, rhsType, type, candidates);
                AddLiftedOperators(type, str, arithmetic, rhsType, type, candidates);
            }
            if (candidates.Count == 0)
            {
                str = str.Substring(3);
                foreach (MethodInfo info in typeof(DefaultOperators).GetMethods())
                {
                    if (info.Name == str)
                    {
                        ParameterInfo[] parameters = info.GetParameters();
                        Type parameterType = parameters[0].ParameterType;
                        Type toType = parameters[1].ParameterType;
                        if (RuleValidation.ImplicitConversion(lhs, parameterType) && RuleValidation.ImplicitConversion(rhs, toType))
                        {
                            candidates.Add(info);
                        }
                    }
                }
                if ((((candidates.Count == 0) && ("Equality" == str)) && (!lhs.IsValueType && !rhs.IsValueType)) && (((lhs == typeof(NullLiteral)) || (rhs == typeof(NullLiteral))) || (lhs.IsAssignableFrom(rhs) || rhs.IsAssignableFrom(lhs))))
                {
                    candidates.Add(ObjectEquality);
                }
                if ((candidates.Count == 0) && ((flag || flag2) || ((lhs == typeof(NullLiteral)) || (rhs == typeof(NullLiteral)))))
                {
                    foreach (MethodInfo info2 in typeof(DefaultOperators).GetMethods())
                    {
                        if (info2.Name == str)
                        {
                            ParameterInfo[] infoArray2 = info2.GetParameters();
                            MethodInfo item = EvaluateLiftedMethod(info2, infoArray2, arithmetic, rhsType, type);
                            if (item != null)
                            {
                                candidates.Add(item);
                            }
                        }
                    }
                }
            }
            if (candidates.Count == 1)
            {
                error = null;
                return candidates[0];
            }
            if (candidates.Count == 0)
            {
                str2 = string.Format(CultureInfo.CurrentCulture, (arithmetic == OperatorGrouping.Arithmetic) ? Messages.ArithOpBadTypes : Messages.RelationalOpBadTypes, new object[] { op.ToString(), (lhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(lhs), (rhs == typeof(NullLiteral)) ? Messages.NullValue : RuleDecompiler.DecompileType(rhs) });
                error = new ValidationError(str2, 0x545);
                return null;
            }
            MethodInfo info4 = validator.FindBestCandidate(null, candidates, new Type[] { lhs, rhs });
            if (info4 != null)
            {
                error = null;
                return info4;
            }
            str2 = string.Format(CultureInfo.CurrentCulture, Messages.AmbiguousOperator, new object[] { op.ToString(), RuleDecompiler.DecompileMethod(candidates[0]), RuleDecompiler.DecompileMethod(candidates[1]) });
            error = new ValidationError(str2, 0x545);
            return null;
        }
コード例 #12
0
        private static object EvaluateBinaryOperation(CodeBinaryOperatorExpression binaryExpr, Type lhsType, object lhsValue, CodeBinaryOperatorType operation, Type rhsType, object rhsValue)
        {
            Literal leftLiteral;
            Literal rightLiteral;
            ArithmeticLiteral leftArithmetic;
            ArithmeticLiteral rightArithmetic;
            string message;
            RuleEvaluationException exception;

            switch (operation)
            {
                case CodeBinaryOperatorType.Add:
                    leftArithmetic = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (leftArithmetic == null)
                        break;
                    rightArithmetic = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (rightArithmetic == null)
                        break;
                    return leftArithmetic.Add(rightArithmetic);
                case CodeBinaryOperatorType.Subtract:
                    leftArithmetic = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (leftArithmetic == null)
                        break;
                    rightArithmetic = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (rightArithmetic == null)
                        break;
                    return leftArithmetic.Subtract(rightArithmetic);
                case CodeBinaryOperatorType.Multiply:
                    leftArithmetic = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (leftArithmetic == null)
                        break;
                    rightArithmetic = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (rightArithmetic == null)
                        break;
                    return leftArithmetic.Multiply(rightArithmetic);
                case CodeBinaryOperatorType.Divide:
                    leftArithmetic = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (leftArithmetic == null)
                        break;
                    rightArithmetic = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (rightArithmetic == null)
                        break;
                    return leftArithmetic.Divide(rightArithmetic);
                case CodeBinaryOperatorType.Modulus:
                    leftArithmetic = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (leftArithmetic == null)
                        break;
                    rightArithmetic = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (rightArithmetic == null)
                        break;
                    return leftArithmetic.Modulus(rightArithmetic);
                case CodeBinaryOperatorType.BitwiseAnd:
                    leftArithmetic = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (leftArithmetic == null)
                        break;
                    rightArithmetic = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (rightArithmetic == null)
                        break;
                    return leftArithmetic.BitAnd(rightArithmetic);
                case CodeBinaryOperatorType.BitwiseOr:
                    leftArithmetic = ArithmeticLiteral.MakeLiteral(lhsType, lhsValue);
                    if (leftArithmetic == null)
                        break;
                    rightArithmetic = ArithmeticLiteral.MakeLiteral(rhsType, rhsValue);
                    if (rightArithmetic == null)
                        break;
                    return leftArithmetic.BitOr(rightArithmetic);

                case CodeBinaryOperatorType.ValueEquality:
                    leftLiteral = Literal.MakeLiteral(lhsType, lhsValue);
                    if (leftLiteral == null)
                        break;
                    rightLiteral = Literal.MakeLiteral(rhsType, rhsValue);
                    if (rightLiteral == null)
                        break;
                    return leftLiteral.Equal(rightLiteral);
                case CodeBinaryOperatorType.IdentityEquality:
                    return lhsValue == rhsValue;
                case CodeBinaryOperatorType.IdentityInequality:
                    return lhsValue != rhsValue;

                case CodeBinaryOperatorType.LessThan:
                    leftLiteral = Literal.MakeLiteral(lhsType, lhsValue);
                    if (leftLiteral == null)
                        break;
                    rightLiteral = Literal.MakeLiteral(rhsType, rhsValue);
                    if (rightLiteral == null)
                        break;
                    return leftLiteral.LessThan(rightLiteral);
                case CodeBinaryOperatorType.LessThanOrEqual:
                    leftLiteral = Literal.MakeLiteral(lhsType, lhsValue);
                    if (leftLiteral == null)
                        break;
                    rightLiteral = Literal.MakeLiteral(rhsType, rhsValue);
                    if (rightLiteral == null)
                        break;
                    return leftLiteral.LessThanOrEqual(rightLiteral);
                case CodeBinaryOperatorType.GreaterThan:
                    leftLiteral = Literal.MakeLiteral(lhsType, lhsValue);
                    if (leftLiteral == null)
                        break;
                    rightLiteral = Literal.MakeLiteral(rhsType, rhsValue);
                    if (rightLiteral == null)
                        break;
                    return leftLiteral.GreaterThan(rightLiteral);
                case CodeBinaryOperatorType.GreaterThanOrEqual:
                    leftLiteral = Literal.MakeLiteral(lhsType, lhsValue);
                    if (leftLiteral == null)
                        break;
                    rightLiteral = Literal.MakeLiteral(rhsType, rhsValue);
                    if (rightLiteral == null)
                        break;
                    return leftLiteral.GreaterThanOrEqual(rightLiteral);

                default:
                    // should never happen
                    // BooleanAnd & BooleanOr short-circuited before call
                    // Assign disallowed at validation time
                    message = string.Format(CultureInfo.CurrentCulture, Messages.BinaryOpNotSupported, operation.ToString());
                    exception = new RuleEvaluationException(message);
                    exception.Data[RuleUserDataKeys.ErrorObject] = binaryExpr;
                    throw exception;
            }

            message = string.Format(CultureInfo.CurrentCulture,
                Messages.BinaryOpFails,
                operation.ToString(),
                RuleDecompiler.DecompileType(lhsType),
                RuleDecompiler.DecompileType(rhsType));
            exception = new RuleEvaluationException(message);
            exception.Data[RuleUserDataKeys.ErrorObject] = binaryExpr;
            throw exception;
        }