-
-
Notifications
You must be signed in to change notification settings - Fork 239
Description
When using an in expression without substitution values, e.g. qry.Where("it.TestEnum in (\"Var1\", \"Var2\")"), the parser checks whether the left side is an Enum and then converts the string values.
When using in @0 syntax, e.g. qry.Where("it.TestEnum in @0", new[] { "Var1", "Var2" }), there is no conversion and an exception is thrown.
[Fact]
public void ExpressionTests_In_Enum()
{
// Arrange
var model1 = new ModelWithEnum { TestEnum = TestEnum.Var1 };
var model2 = new ModelWithEnum { TestEnum = TestEnum.Var2 };
var model3 = new ModelWithEnum { TestEnum = TestEnum.Var3 };
var qry = new[] { model1, model2, model3 }.AsQueryable();
// Act
var expected = qry.Where(x => new[] { TestEnum.Var1, TestEnum.Var2 }.Contains(x.TestEnum)).ToArray();
var result1 = qry.Where("it.TestEnum in (\"Var1\", \"Var2\")").ToArray();
var result2 = qry.Where("it.TestEnum in (0, 1)").ToArray();
+ var result3 = qry.Where("it.TestEnum in @0", new[] { TestEnum.Var1, TestEnum.Var2 }); // works
+ var result4 = qry.Where("it.TestEnum in @0", new[] { "Var1", "Var2" }); // fails
// Assert
Check.That(result1).ContainsExactly(expected);
Check.That(result2).ContainsExactly(expected);
}I'm not sure if the existing logic can be easily extended. Copying existing conversion logic breaks result3 and there is also a check on implementing IEnumerable that would clash.
System.Linq.Dynamic.Core/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
Lines 377 to 388 in 53361d6
| // if the identifier is an Enum (or nullable Enum), try to convert the right-side also to an Enum. | |
| if (TypeHelper.GetNonNullableType(left.Type).GetTypeInfo().IsEnum) | |
| { | |
| if (right is ConstantExpression constantExprRight) | |
| { | |
| right = ParseEnumToConstantExpression(token.Pos, left.Type, constantExprRight); | |
| } | |
| else if (_expressionHelper.TryUnwrapAsConstantExpression(right, out var unwrappedConstantExprRight)) | |
| { | |
| right = ParseEnumToConstantExpression(token.Pos, left.Type, unwrappedConstantExprRight); | |
| } | |
| } |
System.Linq.Dynamic.Core/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
Lines 414 to 421 in 53361d6
| else if (_textParser.CurrentToken.Id == TokenId.Identifier) // a single argument | |
| { | |
| Expression right = ParsePrimary(); | |
| if (!typeof(IEnumerable).IsAssignableFrom(right.Type)) | |
| { | |
| throw ParseError(_textParser.CurrentToken.Pos, Res.IdentifierImplementingInterfaceExpected, typeof(IEnumerable)); | |
| } |