2

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

10
  • 1
    It's not clear why you need to use dynamic LINQ at all here. What's dynamic in your case? Commented Dec 23, 2014 at 12:10
  • @JonSkeet I build that expression outside for filtering a 3rd party grid widget. Commented Dec 23, 2014 at 12:12
  • That's not a terribly clear description - it doesn't give us much more context. Could you perform this part of the query with normal LINQ to Objects, then use that as a source for dynamic LINQ for the widget integration? Commented Dec 23, 2014 at 12:13
  • @JonSkeet I'm trying to include all the relevant information without posting hundreds of lines. I've updated, I hope it clearifies the question. Btw, the question I linked this haves the same problem in a different explanation. Commented Dec 23, 2014 at 12:27
  • If you're already writing code to handle each operator separately, I don't see why you'd want to use dynamic LINQ - I'd just convert each operator to a Func<T, bool> for the relevant type... the more you can do in "normal" LINQ to Objects, the easier it will be. Commented Dec 23, 2014 at 12:32

1 Answer 1

1

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)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.