0

How can I define an array inside of a dynamic linq expression string, that I can pass into .Where(string) ? I already tried { "val a", "val b", "val c" }, but this does not work.

Here's an example of what I want to achieve:

public class Person
{
    String Name { get; set; }
    int Age { get; set; }
}

Now I want to query an IQueryable<Person> using a completely dynamically created dynamic linq expression string, where e.g. Name is queried against a list of predefined values. The following works, but is cumbersome when there are a lot of values:

myQueryablePersons.Where("Name == \"John Doe\" || Name == \"Mr Smith\" || Name == \"CatWoman\");

What I'd like to do is something like this:

myQueryablePersons.Where("{ \"John Doe\", \"Mr Smith\", \"CatWoman\" }.Contains(Name)");

I know how this can achieved using plain C# or plain Linq, but I want to do it by only using the string passed into Where() . Is this possible at all? I already searched other answers on Stackoverflow and other sites, but could not find any answer that really fits my specific question.

Slayer
  • 1
  • 3
  • 1
    Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. – sujith karivelil Apr 10 '17 at 07:14
  • 2
    Share you code, specify your problem. Give example like "this is the input, this is the output but here is the expected output". – Berkay Yaylacı Apr 10 '17 at 07:16
  • 1
    And tell us *exactly* which dynamic linq you are using (there are like two or three different implementations) – xanatos Apr 10 '17 at 07:18
  • What do you want `Where({ "val a", "val b", "val c" })` to do? Please be more specific on what you want to achieve. – MakePeaceGreatAgain Apr 10 '17 at 07:27
  • Possibel duplicate of http://stackoverflow.com/questions/9505189/dynamically-generate-linq-queries – MakePeaceGreatAgain Apr 10 '17 at 07:35

2 Answers2

0

I don't think dynamic linq supports the creation of arrays "inline". What you can do is pass it as an argument:

var persons = new[]
{
    new Person { Name = "John Doe" }
};

var names = new[] { "John Doe", "Mr Smith" };
var res = persons.AsQueryable().Where("@0.Contains(Name)", names).ToArray();
xanatos
  • 109,618
  • 12
  • 197
  • 280
0

Short answer: no

Long answer:

I got this snippet working

Int32List("40, 6, 27").Contains(40) == True

Using this hack Call function in dynamic linq

public class Int32List : List<int>
{
    public Int32List(string arr) : base(arr.Split(',').Select(a => int.Parse(a.Trim())))
    {
    }
}

(I tried params int[] but the string parser doesn't like that)

public static class ExpressionHelper
{
    //https://stackoverflow.com/questions/18313362/call-function-in-dynamic-linq
    private static bool _utilsAdded = false;
    private static void AddUtilites()
    {
        if (_utilsAdded == true)
            return;

        _utilsAdded = true;
        var type = typeof(DynamicQueryable).Assembly.GetType("System.Linq.Dynamic.ExpressionParser");

        FieldInfo field = type.GetField("predefinedTypes", BindingFlags.Static | BindingFlags.NonPublic);

        Type[] predefinedTypes = (Type[])field.GetValue(null);

        Array.Resize(ref predefinedTypes, predefinedTypes.Length + 1);
        predefinedTypes[predefinedTypes.Length - 1] = typeof(Int32List); // Your type

        field.SetValue(null, predefinedTypes);
    }
}

Just call ExpressionHelper.AddUtilities() before your first Dynamic Linq call because it caches the accessible types.

In your case it would be

myQueryablePersons.Where("StringList(\"John Doe, Mr Smith, CatWoman\").Contains(Name)")

But your strings cant contain any commas with this setup. This is the only way I was able to make it work without using a fork

Also this page is helpful: https://github.com/kahanu/System.Linq.Dynamic/wiki/Dynamic-Expressions#operators

If you need to access the element in the array use the "it" keyword

StringList(\"John Doe, Mr Smith, CatWoman\").Any(it == "John Doe") == True