Let's say I have this expression:
int setsize = 20; Expression<Func<Foo, bool>> predicate = x => x.Seed % setsize == 1 || x.Seed % setsize == 4;
This basically โdividesโ a set of elements into 20 sections and extracts every first and fourth elements from each set.
This expression is passed to MongoDB , which driver perfectly translates into a MongoDB "query". The predicate can, however, also be used in the list of objects (LINQ2Objects), etc. I want this expression to be reused ( DRY ). However, I want to be able to pass an IEnumerable<int> to indicate which elements will be retrieved (therefore 1 and 4 are not "hard-coded" into it):
public Expression<Func<Foo, bool>> GetPredicate(IEnumerable<int> items) {
Using LINQPad with this code:
int setsize = 20; Expression<Func<Foo, bool>> predicate = x => x.Seed % setsize == 1 || x.Seed % setsize == 4; predicate.Dump(); } class Foo { public int Seed { get; set; }
I can check the expression:

Now I want to be able to build an exact reproduction of this expression, but with a variable number of integers (so that instead of 1 and 4 I could pass, for example, [1, 5, 9, 11] or [8] or [1, 2, 3, 4, 5, 6, ..., 16] ).
I tried using BinaryExpressions , etc., but could not build this message correctly. The main problem is that most of my attempt will fail when passing the MongoDB predicate. The "hardcoded" version works fine , but somehow all my attempts to pass my dynamic expressions cannot be translated into a MongoDB request using the C # driver:
{ "$or" : [{ "Seed" : { "$mod" : [20, 1] } }, { "Seed" : { "$mod" : [20, 4] } }] }
Basically, I want to dynamically build the expression at run time so that it accurately reproduces what the compiler generates for the "hard-coded" version.
Any help would be appreciated.
EDIT
As requested in the comments (and posted on pastebin ), one of my attempts below. I post it in the question of links to the Fรผhrer if Pastebin takes it or stops them serivce or ...
using MongoRepository; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; class Program { static void Main(string[] args) { MongoRepository<Foo> repo = new MongoRepository<Foo>(); var reporesult = repo.All().Where(IsInSet(new[] { 1, 4 }, 20)).ToArray(); } private static Expression<Func<Foo, bool>> IsInSet(IEnumerable<int> seeds, int setsize) { if (seeds == null) throw new ArgumentNullException("s"); if (!seeds.Any()) throw new ArgumentException("No sets specified"); return seeds.Select<int, Expression<Func<Foo, bool>>>(seed => x => x.Seed % setsize == seed).JoinByOr(); } } public class Foo : Entity { public int Seed { get; set; } } public static class Extensions { public static Expression<Func<T, bool>> JoinByOr<T>(this IEnumerable<Expression<Func<T, bool>>> filters) { var firstFilter = filters.First(); var body = firstFilter.Body; var param = firstFilter.Parameters.ToArray(); foreach (var nextFilter in filters.Skip(1)) { var nextBody = Expression.Invoke(nextFilter, param); body = Expression.Or(body, nextBody); } return Expression.Lambda<Func<T, bool>>(body, param); } }
The result is: Unsupported where clause: <InvocationExpression> .