.net - 构建 'flat'而不是 'tree' LINQ表达式

标签 .net linq wcf-data-services

我正在使用一些代码(在MSDN上可用here)动态构建包含多个OR'子句'的LINQ表达式。

相关代码是

var equals = values.Select(value => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));

var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));

这将生成一个类似于以下内容的LINQ表达式:
(((((ID = 5) OR (ID = 4)) OR (ID = 3)) OR (ID = 2)) OR (ID = 1))

使用此表达式时,我达到了递归限制(100),所以我想生成一个看起来像这样的表达式:
(ID = 5) OR (ID = 4) OR (ID = 3) OR (ID = 2) OR (ID = 1)

我将如何修改表达式构建代码来做到这一点?

最佳答案

您需要修改生成,以便生成平衡树,而不是OR序列,其中左子树是单个表达式,而右子树包含所有剩余元素。图形化:

 Your code               Better
 ---------              --------
    OR                     OR
 #1    OR              OR      OR
     #2  OR          #1  #2  #3  #4
       #3  #4

如您所见,即使在这种简单情况下,更好的方法也不是那么深入(递归嵌套)。可以使用C#作为递归方法来编写生成更好的表达式树的代码:
Expression GenerateTree(List<Expression> exprs, int start, int end) {
  // End of the recursive processing - return single element
  if (start == end) return exprs[start];

  // Split the list between two parts of (roughly the same size)
  var mid = start + (end - start)/2;
  // Process the two parts recursively and join them using OR
  var left = GenerateTree(exprs, start, mid);
  var right = GenerateTree(exprs, mid+1, end);
  return Expression.Or(left, right);
}

// Then call it like this:
var equalsList = equals.ToList();
var body = GenerateTree(equalsList, 0, equalsList.Length);

我没有尝试该代码,因此可能会出现一些小错误,但是它应该可以说明问题。

关于.net - 构建 'flat'而不是 'tree' LINQ表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2940045/

相关文章:

c# - 如何将模型从 View 传递到局部 View ?

c# - 在 .net 控制台应用程序中显示百分比

c# - 将 Enum.GetName(...) 合并到 Linq 查询中

c# - 在 LINQ to Objects 中使用 Max() 后如何选择多个值?

c# - LINQ-所有条件

wcf-data-services - 通过NetFlix odata结果进行分页

entity-framework - Entity Framework - 避免序列化中的循环关系

c# - ADO 数据服务的预测

c# - DataGridView如何实现自动滚动?

c# - 有没有任何工具可以帮助我们将 IEnumerator 属性重构为 IList<T> 或类似的?