I want to perform a Dynamic Lambda in a collection with an array of strings[] on it:
public class ClassStudentsViewModel
{
public string[] Disciplines { get; set; }
public TeacherName { get; set; }
}
This is what I'm trying:

The source is a collection of ClassStudentsViewModel and the values is an array of strings with one string. When executed, it throws me this exception:
No property or field 'y' exists in type 'String'
After some searching, I have found this question which is almost the same problem and the OP ended changing the source code of Dynamic.cs, that isn't a nice option for me. I wonder what I'm trying isn't supported or might be a bug. The problem is that the above mantioned question was asked almost 4 years ago.
The following snippet works nice:
classStudents.AsQueryable().Where(x => x.Disciplines.Any(y => y == "Turma 2")).ToList();
How can I get rid of that error?
UPDATE:
A little context of what I'm trying: My controller receives a viewModel with a collection of filters sent by the 3rd party grid, which contains basically a value and a operator, like eq, gt etc... A method loops all those filters and transforms on lambda operators, like eq to == or contains to .Contains(). In a simple string property like TeacherName(updated viewModel above), the dynamic filters works, e.g. if the predicate in the screenshot is: "TeacherName.Contains(@0)" it works well.
UPDATE 2:
This code generates the predicate:
public static string ToLambdaOperator(string field, string oper, int index, string sufix = null)
{
var result = String.Empty;
switch (oper)
{
case "eq":
case "neq":
case "gte":
case "gt":
case "lte":
case "lt":
result = string.Format(field + ToLinqOperator(oper) + "@" + index);
break;
case "startswith":
result = field + ".StartsWith(" + "@" + index + ")";
break;
case "endswith":
result = field + ".EndsWith(" + "@" + index + ")";
break;
case "contains":
result = field + ".Contains(" + "@" + index + ")";
break;
case "doesnotcontain":
result = "!" + field + ".Contains(" + "@" + index + ") || " + field + ".Equals(String.Empty)";
break;
}
if (!String.IsNullOrEmpty(sufix))
{
result += sufix;
}
return result;
}
// Use example
var operator = "eq";
var paramCounter = -1;
var predicate = ToLambdaOperator("Disciplines.Any(y => y", operator, ++paramCounter, ")");
The predicate above will result: Disciplines.Any(y => y == @0). With the operator contains will result in this: Disciplines.Any(y => y.Contains(@0)).
Func<T, bool>for the relevant type... the more you can do in "normal" LINQ to Objects, the easier it will be.