Nói rằng tôi có biểu hiện này:Runtime tạo LINQ biểu
int setsize = 20;
Expression<Func<Foo, bool>> predicate = x => x.Seed % setsize == 1
|| x.Seed % setsize == 4;
này về cơ bản 'phân vùng' một tập hợp các yếu tố thành 20 phân vùng và lấy từ mỗi mỗi yếu tố đầu tiên và thứ tư được thiết lập.
Biểu thức này được chuyển đến MongoDB mà nó là driver hoàn toàn có khả năng dịch thành truy vấn MongoDB "". Vị từ có thể, tuy nhiên, cũng được sử dụng trên một danh sách các đối tượng (LINQ2Objects) vv Tôi muốn biểu thức này có thể tái sử dụng (DRY). Tuy nhiên, tôi muốn để có thể vượt qua trong một IEnumerable<int>
để xác định các mục để lấy (do 1 và 4 không phải là "mã hóa cứng" vào nó):
public Expression<Func<Foo, bool>> GetPredicate(IEnumerable<int> items) {
//Build expression here and return it
}
Với LINQPad sử dụng mã này:
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; }
tôi có thể kiểm tra các biểu hiện:
Bây giờ, tôi muốn để có thể xây dựng một tái tạo chính xác của biểu thức này nhưng với số lượng biến số nguyên cần vượt qua (vì vậy thay vì 1 và 4 tôi có thể vượt qua, ví dụ: [1, 5, 9, 11]
hoặc [8]
hoặc [1, 2, 3, 4, 5, 6, ..., 16]
).
Tôi đã thử sử dụng BinaryExpressions v.v. nhưng không thể xây dựng thư này chính xác. Vấn đề chính là hầu hết các attempt s của tôi sẽ thất bại khi chuyển vị từ sang MongoDB. Phiên bản "hardcoded" hoạt động tốt nhưng bằng cách nào đó tất cả những nỗ lực của tôi để vượt qua biểu hiện năng động của tôi không được dịch ra tiếng một truy vấn MongoDB bằng C# tài xế:
{
"$or" : [{
"Seed" : { "$mod" : [20, 1] }
}, {
"Seed" : { "$mod" : [20, 4] }
}]
}
Về cơ bản, tôi muốn tự động xây dựng các biểu hiện tại thời gian chạy theo cách sao chép chính xác những gì trình biên dịch tạo ra cho phiên bản 'hardcoded'.
Mọi trợ giúp sẽ được đánh giá cao.
EDIT
As requested in the comments (và posted on pastebin), một trong những cố gắng của tôi dưới đây. Tôi gửi bài nó trong câu hỏi để tham khảo furure nên Pastebin mang nó xuống hoặc ngừng serivce của họ hoặc ...
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);
}
}
Điều này dẫn đến: Unsupported where clause: <InvocationExpression>
.
Vui lòng hiển thị một số - hoặc ít nhất một trong số các lần thử của bạn. –
Ở đây bạn truy cập: http://pastebin.com/qDwXGGit. Điều này dẫn đến: 'Không được hỗ trợ where khoản:'. –
RobIII