Dynamic Lambda condition on nested array

c# dynamic-linq lambda linq

Question

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:

enter image description here

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)).

1
2
5/23/2017 11:43:30 AM

Popular Answer

I think what you are trying to do is to generate an expression tree based on the arguments provided. Here are some examples about how to do that.

https://gist.github.com/afreeland/6733381

How to: Use Expression Trees to Build Dynamic Queries (C# and Visual Basic)

1
2/16/2015 10:30:25 PM


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow