如何实现Linq查询的复用?

咨询区

  • Blaatz0r

我在写 Linq 查询的过程中,遇到了需要复用 Linq 查询条件的问题,比如下面的 Linq 查询:

.Where(x => x.Contains(""));

我能不能将 x => x.Contains("") 提取出然后单独保存起来,再到后续的 linq 查询时复用,比如下面这样。.

.Where(previouslySavedStatement);

回答区

  • Hamid Pourjam

你完全可以将其存放在 变量 中,如果你是在 IQueryable 上扩展的话,可以这么写。

System.Linq.Expressions.Expression<Func<Foo, bool>> selector = x => x.Contains("");

如果是工作在 IEumerable 上,那就是下面这样。

Func<Foo, bool> selector = x => x.Contains("");

最后将 selector 拼到 Where 扩展方法上。

query.Where(selector);
  • crazy_crank

我写了一个叫 CLinq工具包 就是为了解决此类问题的, 你可以在 https://www.nuget.org/packages/CLinq.EntityFramework 上找到为 EF 所作的扩展。

接下来你可以创建任何的 query 片段,比如下面这样。

System.Linq.Expressions.Expression<Func<Foo, bool>> selector = x => x.Contains("");

然后你就可以将 selector 塞入到你的 linq 查询上。

query.AsComposable().Where(o => selector.Pass(o));

除了这种简单的写法,也可以稍微复杂一些,比如条件组合查询。

query.AsComposable().Where(o => selector.Pass(o) || anotherSelector.Pass(o));

甚至可以更复杂一些,比如嵌套。

query.AsComposable().Where(o => anotherSelector.Pass(selector.Pass(o)));

如果你感兴趣,建议看看我的 CLinq 库。

点评区

我相信这是很多 Linq 新手都会遇到的一个问题,想当初 sql 可以各种无底线的拼接,但同样场景放在强类型的linq上就要复杂多了,算是 安全性 和 便捷性 上做了一个取舍吧。