我正在尝试从List<Expression<Func<T, bool>>>
public static IQueryable<T> Search<T>(this IQueryable<T> source, List<Expression<Func<T, bool>>> predicates = null)
where T : EntityObject
{
if (predicates == null || predicates.Count == 0)
return source;
else if (predicates.Count == 1)
return source.Where(predicates[0]);
else
{
var row = Expression.Parameter(typeof(T), "row");
var compoundExpression = predicates[0];
for (int i = 1; i < predicates.Count; i++)
{
compoundExpression = compoundExpression.Or(predicates[i]);
}
return source.Where(compoundExpression);
}
}
static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> lhs, Expression<Func<T, bool>> rhs)
{
var row = Expression.Parameter(typeof(T), "row");
var body = Expression.Or(
Expression.Invoke(lhs, row),
Expression.Invoke(rhs, row));
return Expression.Lambda<Func<T, bool>>(body, row);
}
但是这会返回我的源代码中的每一行?
我正在寻找c=>c.FullName.Contains("Smith") or c=>c.FullName.Contains("Jones")
我已尝试修改使用PredicateBuilder,但它仍然会返回源中的每一行。
public static IQueryable<T> Search<T>(this IQueryable<T> source, List<Expression<Func<T, bool>>> predicates = null)
where T : EntityObject
{
if (predicates == null || predicates.Count == 0)
return source;
else if (predicates.Count == 1)
return source.Where(predicates[0]);
else
{
var pb = PredicateBuilder.False<T>();
for (int i = 0; i < predicates.Count; i++)
{
pb = pb.Or(predicates[i]);
}
return source.AsExpandable().Where(pb);
}
}
非常感谢任何帮助!
最终结果将是允许AND和OR的 例如c =&gt; c.FullName.Contains(“Dav”)AND c =&gt; c.CustomerType =='Staff'
答案 0 :(得分:1)
尝试
public static IQueryable<T> Search<T>(this IQueryable<T> source, IEnumerable<Expression<Func<T, bool>>> predicates = null)
where T : EntityObject
{
if (predicates == null || !predicates.Any())
return source;
else
{
ParameterExpression p = Expression.Parameter(typeof(T), "p");
Expression<Func<T,Bool>> predicate =
Expression.Lambda<Func<T,Bool>(
predicates.Select(l => ReParameteriser(l.Body, l.Paramaters[0], p)
.Aggregate((b1,b2) => Expression.Or(b1,b2)),
new ParamaterExpression[]{p});
return source.Where(predicate);
}
}
public class ReParameteriser : ExpressionVisitor
{
ParameterExpression originalParameter;
ParameterExpression newParameter;
private ReParameteriser(){}
protected ReParameteriser (ParameterExpression originalParameter, ParameterExpression newParameter)
{
this.originalParameter = originalParameter;
this.new = newParameter;
}
public static Expression ReParameterise(Expression expression, ParameterExpression originalParameter, ParameterExpression newParameter)
{
return new ReParameteriser(original,newParameter).Visit(expression);
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == originalParameter)
return newParameter;
else
return node;
}
}
注意:ExpressionVisitor类是.Net4,因此如果您想要定位早期的环境,则需要编写自己的环境。这个代码只是google之一,但通常的资源是Matt Warren的博客http://blogs.msdn.com/b/mattwar/archive/2008/11/18/linq-links.aspx
答案 1 :(得分:1)
有时候周末的代码很奇怪!
不确定我的做法有多么不同,但这是有效的:
public static IQueryable<T> Search<T>(this IQueryable<T> source, List<Expression<Func<T, bool>>> predicates = null)
where T : EntityObject
{
if (predicates == null || predicates.Count == 0)
return source;
else if (predicates.Count == 1)
return source.Where(predicates[0]);
else
{
var query = PredicateBuilder.False<T>();
foreach (var predicate in predicates)
{
query = query.Or(predicate);
}
return source.AsExpandable().Where(query);
}
}
PredicateBuilder似乎是一个很棒的代码。