2014-02-14 4 views
2

У меня есть два выражения linq, которые я хочу комбинировать, но мой код дает мне ошибку. Бинарный оператор И не определен для типов 'System.Func`2[Web.Entities.Customer,System.Boolean]' и 'System.Func`2[Web.Entities.Customer,System.Boolean]'.расчесывание двух выражений linq

У меня есть 2 выражения, например ...

Expression<Func<Customer, bool>> filter = c => c.Active; 
Expression<Func<Customer, bool>> filterz = c => c.Visible; 

я затем объединить их

filter = Expression.Lambda<Func<Customer, bool>>(Expression.And(filter, filterz)); 

Любая помощь по этой проблеме?

спасибо ....

вот updateed код, указанный на рисунке ответ.

public class SwapVisitor : ExpressionVisitor 
{ 

    private readonly Expression from, to; 
    public SwapVisitor(Expression from, Expression to) 
    { 
     this.from = from; 
     this.to = to; 
    } 

    public override Expression Visit(Expression node) 
    { 
     return node == from ? to : base.Visit(node); 
    } 
} 

filter = Expression.Lambda<Func<Customer, bool>>(Expression.AndAlso(
         new SwapVisitor(filter.Parameters[0], filterz.Parameters[0]).Visit(filter.Body), filterz.Body), filterz.Parameters) 
+0

Что вы хотите получить в результате? – Tony

+0

Я хочу передать комбинированное выражение в мой общий репозиторий и передать всем клиентам, которые являются активными и видимыми. У меня уже есть общий общий репозиторий, который я отправляю в фильтр выражений и передаю значения таблицы базы данных через фильтр. –

ответ

1

Вы уже может использовать выражение в хранилище без наружных их объединений:

var yourContext = getContext(); 
var filtered = yourContext.Where(filter).Where(filter2); 

В этом случае объединение не нужно, и этот подход будет работать либо без влияя на эффективность.

Если вам необходимо сочетание:

Попробуйте использовать следующий помощник посетителя:

public class ReplacementVisitor : System.Linq.Expressions.ExpressionVisitor 
{ 
    private readonly Expression _oldExpr; 
    private readonly Expression _newExpr; 
    public ReplacementVisitor(Expression oldExpr, Expression newExpr) 
    { 
     _oldExpr = oldExpr; 
     _newExpr = newExpr; 
    } 

    public override Expression Visit(Expression node) 
    { 
     if (node == _oldExpr) 
      return _newExpr; 
     return base.Visit(node); 
    } 
} 

Нам нужно это, потому что ваши фильтрации выражения используют различные экземпляры параметров. Для объединения нам нужно, чтобы они использовали один и тот же экземпляр параметра. Этот класс помогает нам сделать следующее:

Expression<Func<Customer, bool>> filter = c => c.Active; 
Expression<Func<Customer, bool>> filterz = c => c.Visible; 

var newParameter = Expression.Parameter(typeof(Customer), "x"); 
var visitor1 = new ReplacementVisitor(filter.Parameters[0], newParameter); 
var visitor2 = new ReplacementVisitor(filterz.Parameters[0], newParameter); 

var newLambda = Expression.Lambda(
    Expression.AndAlso(
     visitor1.Visit(filter.Body), 
     visitor2.Visit(filterz.Body) 
    ), 
    newParameter 
); 
+0

Мне нужно комбинировать, потому что deppending на условиях, установленных в перечислении, будет работать с различными условиями фильтрации. Вышеприведенный код лишается базовой версии. –

+0

Хорошо, попробуйте мой обновленный ответ. – Tony

+0

Это тоже не работает. Он проходит через вспомогательный метод, но ничего не возвращается. –

2

, если вы работаете с тем же Customer в каждом фильтре у вас есть, чем вы можете попробовать:

 Expression<Func<Customer, bool>> filter = c => c.Active; 
     Expression<Func<Customer, bool>> filter2 = c => c.Visible; 

     var body = Expression.AndAlso(filter.Body, Expression.Invoke(filter2, filter.Parameters[0])); 

     filter = Expression.Lambda<Func<Customer, bool>>(body, filter.Parameters); 
     var applyFilter = filter.Compile(); 

     var customer = new Customer() { Visible = true, Active = true}; 
     Console.WriteLine(applyFilter(customer)); 

     customer.Active = false; 
     Console.WriteLine(applyFilter(customer)); 

     customer.Visible = false; 
     Console.WriteLine(applyFilter(customer)); 
+1

Это не сработает, потому что тела выражений используют разные экземпляры параметров. – Tony

+0

изменил код –

3
Expression<Func<Customer, bool>> filter1 = c => c.Active; 
Expression<Func<Customer, bool>> filter2 = c => c.Visible; 

var parameter = Expression.Parameter(typeof(Customer), "x"); 

var filter = Expression.Lambda<Func<Customer, bool>>(
       Expression.AndAlso(
        Expression.Invoke(filter1,parameter), 
        Expression.Invoke(filter2,parameter) 
       ),parameter 
      ); 
+0

Вы уверены, что ему нужна побитовая операция? – Tony

+0

@Tony, :) Copy & Paste bug .. –

+0

Invoke не работает на linq для сущностей. –

Смежные вопросы