/// <summary>
        /// If one expression is an enum and the other a string, will convert the string to the enum
        /// </summary>
        /// <param name="exp1">first expression.</param>
        /// <param name="exp2">second expression.</param>
        /// <param name="ignoreCase">if set to <c>true</c> ignore case when parsing</param>
        /// <returns>
        ///   <c>true</c> if expression are now of the same type; otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="NotSupportedException">When the string expression can not be evaluated as a constant.</exception>
        /// <exception cref="EnumParseException">When a string is unable to parse into the enumeration.</exception>
        public static bool TryEnumStringConvert(ref Expression exp1, ref Expression exp2, bool ignoreCase)
        {
            //same type, nothing to do here
            if (exp1.Type == exp2.Type)
            {
                return(true);
            }

            var type1 = Nullable.GetUnderlyingType(exp1.Type) ?? exp1.Type;
            var type2 = Nullable.GetUnderlyingType(exp2.Type) ?? exp2.Type;

            bool ConvertStringExpression(Type enumType, Type enumUnderlyingType, ref Expression stringExpression)
            {
                var isNullable = enumType != enumUnderlyingType;

                //we will only support string constants to convert to enums. This prevents having enum
                //parse errors while evaluating the final expression
                if (!ExpressionEvaluator.TryEvaluate(stringExpression, out string stringConstant))
                {
                    throw new NotSupportedException("Only string constants can be converted to an enum. String expressions can not be parsed as an enum.");
                }

                //Enum.Parse will fail for null, however if we have a nullable enum a null is valid
                if (stringConstant == null && isNullable)
                {
                    stringExpression = ExpressionConversions.Convert(Expression.Constant(null), enumType);
                    return(true);
                }
                try
                {
                    var parsedEnum = Enum.Parse(enumUnderlyingType, stringConstant, ignoreCase);
                    stringExpression = ExpressionConversions.Convert(Expression.Constant(parsedEnum), enumType);
                    return(true);
                }
                catch (ArgumentException ex)
                {
                    //enum parse failures give unhelpful errors, we will catch and rethrow an error with
                    //some more details
                    throw new EnumParseException(stringConstant, enumType, ex);
                }
            };

            if (type2 == typeof(string) && type1.GetTypeInfo().IsEnum)
            {
                return(ConvertStringExpression(exp1.Type, type1, ref exp2));
            }
            else if (type1 == typeof(string) && type2.GetTypeInfo().IsEnum)
            {
                return(ConvertStringExpression(exp2.Type, type2, ref exp1));
            }

            return(false);
        }
Beispiel #2
0
        /// <summary>
        /// Attempt to convert the expression into a boolean.
        /// </summary>
        /// <param name="exp"></param>
        /// <returns></returns>
        public static bool TryBoolean(ref Expression exp)
        {
            if (exp.Type == typeof(bool))
            {
                return(true);
            }

            var left  = exp;
            var right = (Expression)Expression.Constant(true);

            if (!ExpressionConversions.TryImplicitlyConvert(ref left, ref right))
            {
                return(false);
            }
            exp = Expression.Equal(left, right);
            return(true);
        }