我有一个包含多个字段的表单(公司名称,邮政编码等),允许用户搜索数据库中的公司.如果用户在多个字段中输入值,那么我需要搜索所有这些字段.我正在使用LINQ来查询数据库.
到目前为止,我已经设法编写了一个函数,它将查看它们的输入并将其转换为表达式列表.我现在想将该List转换为单个表达式,然后我可以通过LINQ提供程序执行该表达式.
我最初的尝试如下
private Expression<Func<Company, bool>> Combine(IList<Expression<Func<Company, bool>>> expressions)
{
if (expressions.Count == 0)
{
return null;
}
if (expressions.Count == 1)
{
return expressions[0];
}
Expression<Func<Company, bool>> combined = expressions[0];
expressions.Skip(1).ToList().ForEach(expr => combined = Expression.And(combined, expr));
return combined;
}
Run Code Online (Sandbox Code Playgroud)
但是,这会失败,并出现"二进制运算符并且未定义..."的异常消息.有没有人有任何想法,我需要做什么来结合这些表达式?
编辑:更正了我忘记将结果和表达式一起分配给变量的行.谢谢你指出那些人.
jas*_*son 25
你可以Enumerable.Aggregate结合使用Expression.AndAlso.这是一个通用版本:
Expression<Func<T, bool>> AndAll<T>(
IEnumerable<Expression<Func<T, bool>>> expressions) {
if(expressions == null) {
throw new ArgumentNullException("expressions");
}
if(expressions.Count() == 0) {
return t => true;
}
Type delegateType = typeof(Func<,>)
.GetGenericTypeDefinition()
.MakeGenericType(new[] {
typeof(T),
typeof(bool)
}
);
var combined = expressions
.Cast<Expression>()
.Aggregate((e1, e2) => Expression.AndAlso(e1, e2));
return (Expression<Func<T,bool>>)Expression.Lambda(delegateType, combined);
}
Run Code Online (Sandbox Code Playgroud)
您当前的代码永远不会分配给combined:
expr => Expression.And(combined, expr);
Run Code Online (Sandbox Code Playgroud)
返回一个新的Expression,它是按位combined和的结果,expr但它没有变异combined.
编辑:杰森的答案现在比表达树的东西更全面,所以我删除了那一点.但是,我想留下这个:
我假设你正在使用这些作为一个Where条款...为什么不依次调用每个表达式的Where?这应该具有相同的效果:
var query = ...;
foreach (var condition in conditions)
{
query = query.Where(condition);
}
Run Code Online (Sandbox Code Playgroud)