2010-07-20 29 views
14

Làm cách nào để kết hợp hai biểu thức lambda thành một bằng cách sử dụng OR?Biểu thức Lambda và cách kết hợp chúng?

Tôi đã thử những điều sau đây nhưng việc sáp nhập họ đòi hỏi tôi phải vượt qua các thông số vào Expression.Invoke cuộc gọi, tuy nhiên tôi muốn giá trị chuyển vào lambda mới được thông qua vào mỗi đứa trẻ-lambda ..

Expression<Func<int, bool>> func1 = (x) => x > 5; 
Expression<Func<int, bool>> func2 = (x) => x < 0; 
//Combines the lambdas but result in runtime error saying I need to pass in arguments 
//However I want the argument passed into each child lambda to be whatever is passed into the new main lambda 
Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(Expression.Or(Expression.Invoke(func1), Expression.Invoke(func2))); 

//The 9 should be passed into the new lambda and into both child lambdas 
bool tst = lambda.Compile().Invoke(9); 

Bất kỳ ý tưởng nào về cách kết hợp hai biểu thức lambda thành một và có đối số của lambdas con là của cha mẹ?

+1

Khi bạn nói "kết hợp", bạn thực sự muốn điều gì xảy ra? Giả sử đối số được truyền là '7' -' func1' sẽ trả về true và 'func2' sẽ trả về false. Bạn muốn kết hợp trở lại như thế nào? –

Trả lời

18

Cách tốt nhất tôi tìm thấy để học biểu thức là xem mã nguồn của PredicateBuilder.

Khi bạn muốn kết hợp nhiều báo cáo của bạn, bạn có thể:

Expression<Func<int, bool>> func1 = (x) => x > 5; 
Expression<Func<int, bool>> func2 = (x) => x > 10; 

var invocation = Expression.Invoke(func2, func1.Parameters.Cast<Expression>()); 
var expression = Expression.Lambda<Func<int, bool>>(Expression.OrElse(func1.Body, invocation), func1.Parameters); 

Các Expression.Invoke tạo ra một InvocationExpression áp dụng các thông số để func2 của bạn.

Thực tế, PredicateBuilder có thể là mọi thứ bạn cần.

var predicate = PredicateBuilder.False<int>(); 
predicate = predicate.Or(x => x > 5); 
predicate = predicate.Or(x => x > 10); 

Tôi sẽ sửa lại "x > 5 hoặc x > 10", có vẻ như một điều kỳ quặc đối với HOẶC.

Hy vọng điều đó sẽ hữu ích.

+0

Tuyệt vời, đây chỉ là những gì tôi đang tìm kiếm. –

+1

'Expression.Lamda' bị thiếu 'b', vì vậy phải là .Expression.Lambda ' – Bern

+2

'Expression.Invoke' không được hỗ trợ bởi LINQ to Entities bằng cách này. Vì vậy, mặc dù điều này sẽ biên dịch sang IL. Nó sẽ không biên dịch sang SQL. – Aron

1

Thú vị ... Tôi không biết nhiều về biểu thức lambda, nhưng tôi đã tìm thấy this article. Dưới PredicateBuilder Source Code là một ví dụ cho hoặc mà làm việc cho tôi:

public static Expression<Func<T, bool>> Or<T>(
         this Expression<Func<T, bool>> expr1, 
         Expression<Func<T, bool>> expr2) 
{ 
    var invExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>()); 
    return Expression.Lambda<Func<T, bool>> 
     (Expression.OrElse(expr1.Body, invExpr), expr1.Parameters); 
} 
0

** chỉnh sửa: oops đọc qua điều OR, cập nhật nó ***

Hi,

Không chắc chắn nếu bạn chỉ muốn gọi họ seperatley hoặc bạn muốn kết hợp chúng từ một quan điểm học tập của xem.

Bạn chỉ có thể gọi họ là như thế này:

bool OR(int i1, Func<int, bool> f1, Func<int, bool> f2){ 
    return f1(i1) || f2(i1); 
} 

Điều đó sẽ làm các trick.

hoặc bạn có thể viết lại rằng khi

bool MyOR = (i1, f1, f2) => f1(i1) || f2(i1); 

Và khi bạn đang qurious, tạo ra một biểu hiện từ đó và nhìn vào đó. (Làm điều này bằng tay, don; t có VS ở đây bây giờ, vì vậy hãy dễ dàng trên lỗi chính tả của tôi)

Expression<Func<int, Func<int, bool>, Func<int, bool>, bool>> exprOR = 
(i1, f1, f2) => f1(i1) || f2(i1); 

Nếu bạn muốn xem xét giải phẫu của biểu thức, bạn có thể nhìn vào bài viết này tôi đã viết: http://www.codeproject.com/KB/WPF/WpfExpressionTree.aspx

Chỉ cần chuyển biểu thức cho người theo dõi và xem cách nó được xây dựng.

Trân Gert-Jan

1

Tại sao không chỉ làm:

Func<int, bool> func1 = (x) => x > 5; 
Func<int, bool> func2 = (x) => x > 10; 

List<Func<int, bool>> funcs = new List<Func<int, bool>> { func1, func2 }; 

var value = 7; 

Console.WriteLine(funcs.Any(x => x(value))); // OR 
Console.WriteLine(funcs.All(x => x(value))); // AND 

?

Tiết kiệm phiền toái với thư viện của bên thứ ba.

+0

Vấn đề là tôi muốn giữ chúng trong một cây biểu thức, vì vậy chúng được phân tách bằng khung thực thể ... –

+1

Đủ công bằng, đề xuất của tôi có lẽ không phải là khả thi –

Các vấn đề liên quan