2010-12-11 37 views
17

Tôi đang tìm cách loại bỏ cụm từ được sử dụng để lọc các chuỗi IQueryable. một cái gì đóC# phủ nhận biểu thức

Vì vậy, tôi đã có như:

Expression<Func<T, bool>> expression = (x => true); 

Bây giờ tôi muốn tạo cụm từ đó sẽ dẫn đến năng suất (x => false) - vì vậy tôi về cơ bản muốn phủ nhận expression.

Các phương pháp làm việc tôi đã tìm thấy bản thân mình làm việc như thế này:

var negatedExpression = 
    Expression.Lambda<Func<T, bool>> (Expression.Not(expression.Body), 
            expression.Parameters[0]))); 

Nhưng tôi gần như chắc chắn có một cách tốt hơn - bạn có thể giúp tôi? (giống như Not(expression), có thể).

Trả lời

17

Một phương pháp mở rộng dễ dàng:

public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> one) 
{ 
    var candidateExpr = one.Parameters[0]; 
    var body = Expression.Not(one.Body); 

    return Expression.Lambda<Func<T, bool>>(body, candidateExpr); 
} 

Cách sử dụng:

Expression<Func<int, bool>> condition = x => x > 5; 
var source = Enumerable.Range(1, 10); 
var result1 = source.Where(condition.Compile()); //6,7,8,9,10 
var result2 = source.Where(condition.Not().Compile()); //1,2,3,4,5 
+0

Vâng, tôi biết cách phủ nhận một tuyên bố thành một phương pháp 'Không', nhưng tôi thực sự đang tìm kiếm một cách dễ dàng để thực sự phủ định * (nó nhìn tôi gọi là 'Expression.Lambda. Blablabla' là một overkill rất lớn). * –

+2

Cây biểu hiện là bất biến, vì vậy bạn phải tạo ra một lambda mới. –

-2

Điều này thì sao?

Expression<Func<bool>> expr =() => true; 
Expression<Func<bool>> negated =() => !expr.Compile()(); 
+0

Bạn vừa chuyển biểu thức nhập thành cuộc gọi phương thức mờ. Điều này không giúp gì cả vì mục đích của việc sử dụng một biểu thức là truy vấn được cung cấp có thể hiểu được nó. – CodesInChaos

1

viết bài để tham khảo trong tương lai.

Danny Chen của câu trả lời có thể được thực hiện chung chung hơn:

public static Expression<TFunc> Not<TFunc>(this Expression<TFunc> baseExpr) 
{ 
    var param = baseExpr.Parameters; 
    var body = Expression.Not(baseExpr.Body); 
    var newExpr = Expression.Lambda<TFunc>(body, param); 
    return newExpr; 
} 

Phiên bản này có thể nhận được một biểu thức với bất kỳ số lượng các thông số đầu vào. Nó chỉ thêm một chút khả năng sử dụng, tuy nhiên, vì Biểu thức rất có thể sẽ được chuyển đến một hàm như IEnumerable.Where.

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