根据我昨天提出的问题:
如果我必须附加到我现有的'where'表达式,我将如何追加?
Expression<Func<Client, bool>> clientWhere = c => true;
if (filterByClientFName)
{
clientWhere = c => c.ClientFName == searchForClientFName;
}
if (filterByClientLName)
{
clientWhere = c => c.ClientLName == searchForClientLName;
}
Run Code Online (Sandbox Code Playgroud)
用户可以输入名字或姓氏或两者.如果他们同时输入我想附加到表达式.试着看看是否有相当于我可以做的追加
clientWhere.Append or clientWhere += add new expression
Run Code Online (Sandbox Code Playgroud)
或类似的东西
Jas*_*son 55
我相信你可以做到以下几点:
Expression<Func<Client, bool>> clientWhere = c => true;
if (filterByClientFName)
{
var prefix = clientWhere.Compile();
clientWhere = c => prefix(c) && c.ClientFName == searchForClientFName;
}
if (filterByClientLName)
{
var prefix = clientWhere.Compile();
clientWhere = c => prefix(c) && c.ClientLName == searchForClientLName;
}
Run Code Online (Sandbox Code Playgroud)
如果您需要将所有内容保存在Expression-land(与之一起使用IQueryable),您还可以执行以下操作:
Expression<Func<Client, bool>> clientWhere = c => true;
if (filterByClientFName)
{
Expression<Func<Client, bool>> newPred =
c => c.ClientFName == searchForClientFName;
clientWhere = Expression.Lambda<Func<Freight, bool>>(
Expression.AndAlso(clientWhere, newPred), clientWhere.Parameters);
}
if (filterByClientLName)
{
Expression<Func<Client, bool>> newPred =
c => c.ClientLName == searchForClientLName;
clientWhere = Expression.Lambda<Func<Freight, bool>>(
Expression.AndAlso(clientWhere, newPred), clientWhere.Parameters);
}
Run Code Online (Sandbox Code Playgroud)
通过定义此扩展方法,可以减少这种情况:
public static Expression<TDelegate> AndAlso<TDelegate>(this Expression<TDelegate> left, Expression<TDelegate> right)
{
return Expression.Lambda<TDelegate>(Expression.AndAlso(left, right), left.Parameters);
}
Run Code Online (Sandbox Code Playgroud)
然后你可以使用这样的语法:
Expression<Func<Client, bool>> clientWhere = c => true;
if (filterByClientFName)
{
clientWhere = clientWhere.AndAlso(c => c.ClientFName == searchForClientFName);
}
if (filterByClientLName)
{
clientWhere = clientWhere.AndAlso(c => c.ClientLName == searchForClientLName);
}
Run Code Online (Sandbox Code Playgroud)
Jos*_*dan 12
这是一个复杂的场景.您几乎在LINQ之上构建自己的查询引擎.JaredPar的解决方案(它去了哪里?)如果你想要在所有标准之间进行逻辑AND,那就太棒了,但情况可能并非总是如此.
当我最近在我的一个项目中与此争吵时,我创建了两个列表:
List<Predicate<T>> andCriteria;
List<Predicate<T>> orCriteria;
Run Code Online (Sandbox Code Playgroud)
(在这种情况下,T是客户,为您服务)
我会在列表中填充我想要成为真实的谓词.例如,
decimal salRequirement = 50000.00;
andCriteria.Add(c => c.Salary > salRequirement);
orCriteria.Add(c => c.IsMarried);
Run Code Online (Sandbox Code Playgroud)
然后,我将检查我的Where子句中的列表中的所有条件.例如:
Expression<Func<Client, bool>> clientWhere =
c => andCriteria.All(pred => pred(c) ) && orCriteria.Any(pred => pred(c) );
Run Code Online (Sandbox Code Playgroud)
出于可读性的考虑,这也可以通过for循环完成.在应用OR和AND子句时,请记住使用正确的操作顺序.
如果您遇到类似的问题,您可以在这个伟大的主题中找到所有可能的解决方案。或者只是使用 PredicateBuilder 是这个 poporse 的好帮手。
var predicate = PredicateBuilder.True<Client>();
if (filterByClientFName)
{
predicate = predicate.And(c => c.ClientFName == searchForClientFName);
}
if (filterByClientLName)
{
predicate = predicate.And(c => c.ClientLName == searchForClientLName);
}
var result = context.Clients.Where(predicate).ToArray();
Run Code Online (Sandbox Code Playgroud)
这是一些构建器实现。
public static class PredicateBuilder
{
// Creates a predicate that evaluates to true.
public static Expression<Func<T, bool>> True<T>() { return param => true; }
// Creates a predicate that evaluates to false.
public static Expression<Func<T, bool>> False<T>() { return param => false; }
// Creates a predicate expression from the specified lambda expression.
public static Expression<Func<T, bool>> Create<T>(Expression<Func<T, bool>> predicate) { return predicate; }
// Combines the first predicate with the second using the logical "and".
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.AndAlso);
}
// Combines the first predicate with the second using the logical "or".
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.OrElse);
}
// Negates the predicate.
public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expression)
{
var negated = Expression.Not(expression.Body);
return Expression.Lambda<Func<T, bool>>(negated, expression.Parameters);
}
// Combines the first expression with the second using the specified merge function.
static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
{
// zip parameters (map from parameters of second to parameters of first)
var map = first.Parameters
.Select((f, i) => new { f, s = second.Parameters[i] })
.ToDictionary(p => p.s, p => p.f);
// replace parameters in the second lambda expression with the parameters in the first
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
// create a merged lambda expression with parameters from the first expression
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
}
class ParameterRebinder : ExpressionVisitor
{
readonly Dictionary<ParameterExpression, ParameterExpression> map;
ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
{
this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
}
public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
{
return new ParameterRebinder(map).Visit(exp);
}
protected override Expression VisitParameter(ParameterExpression p)
{
ParameterExpression replacement;
if (map.TryGetValue(p, out replacement))
{
p = replacement;
}
return base.VisitParameter(p);
}
}
}
Run Code Online (Sandbox Code Playgroud)