diff --git a/src/System.Linq.Dynamic.Core/Parser/Constants.cs b/src/System.Linq.Dynamic.Core/Parser/Constants.cs index da3e2e45..86555261 100644 --- a/src/System.Linq.Dynamic.Core/Parser/Constants.cs +++ b/src/System.Linq.Dynamic.Core/Parser/Constants.cs @@ -4,8 +4,9 @@ namespace System.Linq.Dynamic.Core.Parser { internal static class Constants { - public static readonly Expression TrueLiteral = Expression.Constant(true); - public static readonly Expression FalseLiteral = Expression.Constant(false); - public static readonly Expression NullLiteral = Expression.Constant(null); + public static bool IsNull(Expression exp) + { + return exp is ConstantExpression cExp && cExp.Value == null; + } } } diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionHelper.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionHelper.cs index 65ae19ea..bb92daaf 100644 --- a/src/System.Linq.Dynamic.Core/Parser/ExpressionHelper.cs +++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionHelper.cs @@ -256,7 +256,7 @@ public Expression GenerateAndAlsoNotNullExpression(Expression sourceExpression) expresssions.Reverse(); // Convert all expressions into '!= null' - var binaryExpressions = expresssions.Select(expression => Expression.NotEqual(expression, Constants.NullLiteral)).ToArray(); + var binaryExpressions = expresssions.Select(expression => Expression.NotEqual(expression, Expression.Constant(null))).ToArray(); // Convert all binary expressions into `AndAlso(...)` var andAlsoExpression = binaryExpressions[0]; diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs index 4fa446ed..e0c6ff0e 100644 --- a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs +++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs @@ -428,7 +428,7 @@ Expression ParseComparisonOperator() if (isEquality && (!left.Type.GetTypeInfo().IsValueType && !right.Type.GetTypeInfo().IsValueType || left.Type == typeof(Guid) && right.Type == typeof(Guid))) { // If left or right is NullLiteral, just continue. Else check if the types differ. - if (!(left == Constants.NullLiteral || right == Constants.NullLiteral) && left.Type != right.Type) + if (!(Constants.IsNull(left) || Constants.IsNull(right)) && left.Type != right.Type) { if (left.Type.IsAssignableFrom(right.Type)) { @@ -1096,7 +1096,7 @@ Expression ParseFunctionNullPropagation() { var expressionTest = _expressionHelper.GenerateAndAlsoNotNullExpression(memberExpression); var expressionIfTrue = memberExpression; - var expressionIfFalse = args.Length == 2 ? args[1] : Constants.NullLiteral; + var expressionIfFalse = args.Length == 2 ? args[1] : Expression.Constant(null); return GenerateConditional(expressionTest, expressionIfTrue, expressionIfFalse, errorPos); } @@ -1170,12 +1170,12 @@ Expression GenerateConditional(Expression test, Expression expr1, Expression exp if (expr1.Type != expr2.Type) { - if ((expr1 == Constants.NullLiteral && expr2.Type.GetTypeInfo().IsValueType) || (expr2 == Constants.NullLiteral && expr1.Type.GetTypeInfo().IsValueType)) + if ((Constants.IsNull(expr1) && expr2.Type.GetTypeInfo().IsValueType) || (Constants.IsNull(expr2) && expr1.Type.GetTypeInfo().IsValueType)) { // If expr1 is a null constant and expr2 is a IsValueType: // - create nullable constant from expr1 with type from expr2 // - convert expr2 to nullable - if (expr1 == Constants.NullLiteral && expr2.Type.GetTypeInfo().IsValueType) + if (Constants.IsNull(expr1) && expr2.Type.GetTypeInfo().IsValueType) { Type nullableType = typeof(Nullable<>).MakeGenericType(expr2.Type); expr1 = Expression.Constant(null, nullableType); @@ -1185,7 +1185,7 @@ Expression GenerateConditional(Expression test, Expression expr1, Expression exp // If expr2 is a null constant and expr1 is a IsValueType: // - create nullable constant from expr2 with type from expr1 // - convert expr1 to nullable - if (expr2 == Constants.NullLiteral && expr1.Type.GetTypeInfo().IsValueType) + if (Constants.IsNull(expr2) && expr1.Type.GetTypeInfo().IsValueType) { Type nullableType = typeof(Nullable<>).MakeGenericType(expr1.Type); expr2 = Expression.Constant(null, nullableType); @@ -1195,8 +1195,8 @@ Expression GenerateConditional(Expression test, Expression expr1, Expression exp return Expression.Condition(test, expr1, expr2); } - Expression expr1As2 = expr2 != Constants.NullLiteral ? _parsingConfig.ExpressionPromoter.Promote(expr1, expr2.Type, true, false) : null; - Expression expr2As1 = expr1 != Constants.NullLiteral ? _parsingConfig.ExpressionPromoter.Promote(expr2, expr1.Type, true, false) : null; + Expression expr1As2 = !Constants.IsNull(expr2) ? _parsingConfig.ExpressionPromoter.Promote(expr1, expr2.Type, true, false) : null; + Expression expr2As1 = !Constants.IsNull(expr1) ? _parsingConfig.ExpressionPromoter.Promote(expr2, expr1.Type, true, false) : null; if (expr1As2 != null && expr2As1 == null) { expr1 = expr1As2; @@ -1207,8 +1207,8 @@ Expression GenerateConditional(Expression test, Expression expr1, Expression exp } else { - string type1 = expr1 != Constants.NullLiteral ? expr1.Type.Name : "null"; - string type2 = expr2 != Constants.NullLiteral ? expr2.Type.Name : "null"; + string type1 = !Constants.IsNull(expr1) ? expr1.Type.Name : "null"; + string type2 = !Constants.IsNull(expr2) ? expr2.Type.Name : "null"; if (expr1As2 != null) { throw ParseError(errorPos, Res.BothTypesConvertToOther, type1, type2); diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionPromoter.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionPromoter.cs index 1400fac7..1633c3ae 100644 --- a/src/System.Linq.Dynamic.Core/Parser/ExpressionPromoter.cs +++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionPromoter.cs @@ -3,7 +3,7 @@ namespace System.Linq.Dynamic.Core.Parser { - internal class ExpressionPromoter : IExpressionPromoter + public class ExpressionPromoter : IExpressionPromoter { /// public virtual Expression Promote(Expression expr, Type type, bool exact, bool convertExpr) @@ -17,7 +17,7 @@ public virtual Expression Promote(Expression expr, Type type, bool exact, bool c if (ce != null) { - if (ce == Constants.NullLiteral || ce.Value == null) + if (Constants.IsNull(ce)) { if (!type.GetTypeInfo().IsValueType || TypeHelper.IsNullableType(type)) { diff --git a/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs b/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs index 74cc2234..2f9098ea 100644 --- a/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs +++ b/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq.Expressions; namespace System.Linq.Dynamic.Core.Parser { @@ -22,9 +23,9 @@ internal class KeywordsHelper : IKeywordsHelper private readonly IDictionary _keywords = new Dictionary(StringComparer.OrdinalIgnoreCase) { - { "true", Constants.TrueLiteral }, - { "false", Constants.FalseLiteral }, - { "null", Constants.NullLiteral } + { "true", Expression.Constant(true) }, + { "false", Expression.Constant(false) }, + { "null", Expression.Constant(null) } }; public KeywordsHelper(ParsingConfig config)