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