说我有这个表达式:
int setsize = 20;
Expression<Func<Foo, bool>> predicate = x => x.Seed % setsize == 1
|| x.Seed % setsize == 4;
这基本上'分区的一组元素到20个分区的,并且从每个检索设定的每个第一和第四元件。
这个表达式传递到MongoDB中 ,它的驱动程序是完全能够翻译成MongoDB的“查询”的。 谓词可以,但是,也可以的对象(LINQ2Objects)列表等。我想这表达受到重用(在使用DRY )。 然而,我希望能够在传递IEnumerable<int>
指定要检索的项(因此1和4都不是“硬编码”到它):
public Expression<Func<Foo, bool>> GetPredicate(IEnumerable<int> items) {
//Build expression here and return it
}
随着LINQPad使用此代码:
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; }
我可以检查表达式:
现在,我要能够建立这样的表达,但具有整数的可变的量的真实再现通过(所以代替图1和4,我可以通过,例如, [1, 5, 9, 11]
或[8]
或[1, 2, 3, 4, 5, 6, ..., 16]
我已经尝试使用BinaryExpressions等,但一直没能正确地构建该消息。 主要的问题是,大多数我的企图传递谓词MongoDB的当s将失败。 在“硬编码”版本工作正常 ,但不知何故我所有试图通过我的动态表情无法被翻译成由C#驱动程序的MongoDB查询:
{
"$or" : [{
"Seed" : { "$mod" : [20, 1] }
}, {
"Seed" : { "$mod" : [20, 4] }
}]
}
基本上,我要动态地构建在运行时表达的这样一种方式,它究竟是什么复制编译器生成的“硬编码”的版本。
任何帮助将不胜感激。
编辑
按照要求在评论 (和张贴在引擎收录 ),下面我尝试之一。 我张贴在furure参考问题应该引擎收录把它记下来或停止其serivce或...
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);
}
}
这导致: Unsupported where clause: <InvocationExpression>