-
-
Notifications
You must be signed in to change notification settings - Fork 237
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)); | |
} |