Say mam to wyrażenie:Runtime tworzenie LINQ ekspresji
int setsize = 20;
Expression<Func<Foo, bool>> predicate = x => x.Seed % setsize == 1
|| x.Seed % setsize == 4;
Zasadniczo partycje „” zestaw elementów na 20 przegród i pobiera od każdego zestawu każdego pierwszego i czwartego elementu.
To wyrażenie jest przekazywane do MongoDB, które jest w stanie przetworzyć na "kwerendę" MongoDB. Predykatu można jednak używać również na liście obiektów (LINQ2Objects) itp. Chcę, aby to wyrażenie było wielokrotnego użytku (DRY). Jednakże chcę, aby być w stanie przejść w IEnumerable<int>
, aby określić, które elementy do pobrania (czyli 1 i 4 nie są „na sztywno” do niego):
public Expression<Func<Foo, bool>> GetPredicate(IEnumerable<int> items) {
//Build expression here and return it
}
Z LINQPad przy użyciu tego kodu:
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; }
mogę zbadać zależność:
teraz chcę, aby móc zbudować dokładną reprodukcję tej wypowiedzi, ale ze zmienną liczbą liczb całkowitych do przekazania (więc zamiast 1 i 4 mógłbym przejść, na przykład, [1, 5, 9, 11]
lub [8]
lub [1, 2, 3, 4, 5, 6, ..., 16]
).
Próbowałem używać BinaryExpressions itp., Ale nie udało się poprawnie utworzyć tej wiadomości. Głównym problemem jest to, że większość moich attempt s zawiedzie podczas przekazywania predykatu do MongoDB. W „ustalony” wersja działa dobrze ale jakoś wszystkie moje próby przekazać moje wyrazy dynamiczne nie być tłumaczone na zapytania MongoDB przez kierowcę C#:
{
"$or" : [{
"Seed" : { "$mod" : [20, 1] }
}, {
"Seed" : { "$mod" : [20, 4] }
}]
}
Zasadniczo chcę, aby dynamicznie zbudować wyrażenie w czasie wykonywania w taki sposób, aby dokładnie replikował to, co generuje kompilator dla wersji "zakodowanej".
Każda pomoc zostanie doceniona.
EDIT
As requested in the comments (i posted on pastebin), jeden z poniższych moich próbach. Jestem umieszczenie go w pytaniu o furure odniesienia powinny Pastebin wziąć go lub zatrzymać ich serivce lub ...
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);
}
}
Skutkuje: Unsupported where clause: <InvocationExpression>
.
Proszę pokazać niektóre - lub przynajmniej jedno - swoich prób. –
Tutaj możesz: http://pastebin.com/qDwXGGit. Powoduje to: 'Nieobsługiwane gdzie klauzula:'. –
RobIII