/// <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); }
/// <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); }