`it` isn't interpreted as the inner parameter when using `All` or `Any`
The following code:
public class Person {
public string LastName { get; set; |
}
var selector = "LastName.Any(int(it) > 109";
var prm = Parameter(typeof(Person));
var parser = new ExpressionParser(new[] { prm }, selector, new object[] { }, ParsingConfig.Default);
var expr = parser.Parse(null);
fails with:
System.Linq.Dynamic.Core.Exceptions.ParseException: 'A value of type 'Person' cannot be converted to type 'Int32'' while changing
selectorto this:
var selector = "LastName.Any(it == 'c')";
fails similarly with:
System.InvalidOperationException: 'The binary operator Equal is not defined for the types '_DynamicLINQ.Person' and 'System.Char'.'
It seems as though the it when used in the inner lambda is still interpreted as the outer it (in this case, Person and not char).
Note: I didn't test this with other LINQ methods.
This seems to run counter to the documentation:
In the predicate and selector expressions, the members of the current instance for that sequence operator are automatically in scope, and the instance itself can be referenced using the keyword
it.
Hello @zspitz ,
I think you are currently trying to use the library in a way that it was not built for.
As said in the name, the library is made to execute LINQ query such as:
var list = new List<Person>();
list.Add(new Person() {LastName = "a"});
list.Add(new Person() {LastName = "b"});
list.Add(new Person() {LastName = "c"});
var x = list.AsQueryable().Any("it.LastName == \"c\"");
It's not initially intended to be a full C# evaluator. For those, there is our other library C# Eval Expression or perhaps even better for your case Roslyn Scripting.
While this library tries to support as much as possible, it doesn't support everything such as LINQ method in an expression.
@JonathanMagnan
While this library tries to support as much as possible, it doesn't support everything such as LINQ method in an expression.
The documentation suggests that the library does allow certain specific LINQ method calls, even in an expression. As part of the expression language syntax, it has this to say:
A subset of the Standard Query Operators is supported for objects that implement
IEnumerable<T>orIQueryable<T>. Specifically, the following constructs are permitted, where seq is anIEnumerable<T>orIQueryable<T>instance, predicate is a boolean expression and selector is an expression of any type. ... In the predicate and selector expressions, the members of the current instance for that sequence operator are automatically in scope, and the instance itself can be referenced using the keywordit. For example:customers.Where("Orders.Any(Total >= 1000)");
Note that this is distinct from the extension methods provided by Dynamic LINQ.
Here you can see the code which parses specific Enumerable / Queryable methods within the Dynamic LINQ string; and it's called from here.
AFAICT the primary issue is that it already refers to the outer lambda parameter; how should it refer to the inner lambda parameter?
But one way to resolve this might be to allow numbered its: it0 (equivalent to it), it1, it2 etc. This would allow accessing multiple levels of inner lambda parameters.
@JonathanMagnan @StefH Any news/thoughts on this?
https://github.com/zzzprojects/System.Linq.Dynamic.Core/pull/798