的說我有以下表達式:運行時創建LINQ表達
int setsize = 20;
Expression<Func<Foo, bool>> predicate = x => x.Seed % setsize == 1
|| x.Seed % setsize == 4;
這基本上'分區的一組元素到20個分區的,並且從每個設置的每個第一和第四元件檢索。
該表達式被傳遞給MongoDB,它是driver完全能夠翻譯成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等,但一直無法正確構造此消息。主要問題是我的attempt的大多數在將謂詞傳遞給MongoDB時會失敗。 的「硬編碼」版本工作正常但不知何故,所有我試圖通過我的動態表情無法被翻譯成由C#驅動程序的MongoDB查詢:
{
"$or" : [{
"Seed" : { "$mod" : [20, 1] }
}, {
"Seed" : { "$mod" : [20, 4] }
}]
}
基本上,我要動態地構建在運行時的表達以這種方式,它完全複製了編譯器爲「硬編碼」版本生成的內容。
任何幫助將不勝感激。
編輯
As requested in the comments(和posted on pastebin),下面我嘗試之一。我張貼在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>
。
請顯示一些 - 或者至少一個 - 你的嘗試。 –
這裏你去:http://pastebin.com/qDwXGGit。這導致:'Unsupported where clause:'。 –
RobIII