diff --git a/src/DynamicExpresso.Core/Parsing/Parser.cs b/src/DynamicExpresso.Core/Parsing/Parser.cs index 367406cf..7d6e1ae4 100644 --- a/src/DynamicExpresso.Core/Parsing/Parser.cs +++ b/src/DynamicExpresso.Core/Parsing/Parser.cs @@ -2562,10 +2562,14 @@ private Expression GenerateLessThanEqual(Expression left, Expression right) private Expression GenerateBinary(ExpressionType binaryType, Expression left, Expression right) { - if (IsDynamicExpression(left) || IsDynamicExpression(right)) return GenerateBinaryDynamic(binaryType, left, right); + // enum bitwise operations are not resolved properly by Linq + var bitwiseOps = new[] { ExpressionType.Or, ExpressionType.And }; + if (left.Type.IsEnum && right.Type == left.Type && bitwiseOps.Contains(binaryType)) + return GenerateBinaryEnums(binaryType, left, right); + // find the overloaded binary operator string opName; @@ -2607,7 +2611,7 @@ private Expression GenerateBinary(ExpressionType binaryType, Expression left, Ex return Expression.MakeBinary(binaryType, left, right, liftToNull, operatorMethod); } - private Expression GenerateBinaryDynamic(ExpressionType binaryType,Expression left, Expression right) + private Expression GenerateBinaryDynamic(ExpressionType binaryType, Expression left, Expression right) { //binary binder for dynamic type does not support AndAlso and OrElse as valid operations if (binaryType == ExpressionType.AndAlso || binaryType == ExpressionType.OrElse) @@ -2632,6 +2636,17 @@ private Expression GenerateBinaryDynamic(ExpressionType binaryType,Expression le return Expression.Dynamic(binder, typeof(object), left, right); } + private Expression GenerateBinaryEnums(ExpressionType binaryType, Expression left, Expression right) + { + var enumType = left.Type; + var underlyingType = enumType.GetEnumUnderlyingType(); + left = Expression.Convert(left, underlyingType); + right = Expression.Convert(right, underlyingType); + + var op = Expression.MakeBinary(binaryType, left, right); + return Expression.Convert(op, enumType); + } + private MethodData FindBinaryOperator(string operatorName, Expression left, Expression right) { if (operatorName == null) diff --git a/test/DynamicExpresso.UnitTest/GithubIssues.cs b/test/DynamicExpresso.UnitTest/GithubIssues.cs index 56b4cce2..e2e5a28d 100644 --- a/test/DynamicExpresso.UnitTest/GithubIssues.cs +++ b/test/DynamicExpresso.UnitTest/GithubIssues.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Text.RegularExpressions; // ReSharper disable SpecifyACultureInStringConversionExplicitly @@ -528,7 +529,6 @@ public void GitHub_Issue_221_Reflection_not_allowed() Assert.Throws(() => interpreter.Parse("list.SelectMany(t => t.GetMethods())")); } - public static class Utils { public static List Array(IEnumerable collection) => new List(collection); @@ -538,6 +538,22 @@ public static class Utils public static int Any(IEnumerable collection) => 1; public static int Any(IEnumerable collection) => 2; } + + [Test] + public void GitHub_Issue_235() + { + var target = new Interpreter(); + target.Reference(typeof(RegexOptions)); + target.Reference(typeof(DateTimeKind)); + + var result = target.Eval("RegexOptions.Compiled | RegexOptions.Singleline"); + Assert.True(result.HasFlag(RegexOptions.Compiled)); + Assert.True(result.HasFlag(RegexOptions.Singleline)); + + // DateTimeKind doesn't have the Flags attribute: the bitwise operation returns an integer + var result2 = target.Eval("DateTimeKind.Local | DateTimeKind.Utc"); + Assert.AreEqual((DateTimeKind)3, result2); + } } internal static class GithubIssuesTestExtensionsMethods