如何在LINQ语句中重用表达式?

时间:2009-06-12 14:18:25

标签: c# linq lambda

我喜欢为DRY原因重用表达式,但是如何在LINQ语句中重用表达式呢?

e.g。

我有

public static class MyExpressions {
    public static Expression<Func<Product,bool>> IsAGoodProduct() {
        return (p) => p.Quality>3;
    }
}

并且想在LINQ语句中使用它,所以

  var goodProds = from p in dataContext.Products
                  where ????? // how do I use IsAGoodProduct here?
                  select p;

当然,我可以使用IQueryableExtension.Where函数,但这会使联接和其他函数对于更复杂的查询更加困难。

这是可能的还是LINQ的限制?

4 个答案:

答案 0 :(得分:22)

如果您从LINQ语法糖中移出,则有可能:

var goodProds = dataContext.Products.Where(MyExpressions.IsAGoodProduct());

没有它,就不可能。

没有什么可以阻止你混合两种样式来构建单个查询。

示例:

  var goodProds = from p in dataContext.Products
                                       .Where(MyExpressions.IsAGoodProduct())
                  group p by p.Category into g 
                  select new {Category = g.Key, ProductCount = g.Group.Count()};

答案 1 :(得分:3)

我们遇到了同样的问题。它不是开箱即用的支持,它是LOB应用程序的主要问题。我最后编写了一篇关于LINQ表达式重用的代码项目文章,包括一个名为LinqExpressionPrjection的非常小的实用程序,它可以在投影中重用(包括匿名类型)。

找到文章here

您可以将投影重新使用的汇编作为nuget package,并且源位于CodePlex

自您发布以来已经过了一段时间。我希望它对你有用。如果没有,也许是其他人阅读这个帖子。

答案 2 :(得分:3)

我遇到了同样的问题,并希望保留在查询语法中使用扩展方法的能力(与普通支持的函数一样......)。解决方案可能是this library

您只需将该方法重复使用两次,一次用于一般用途,一次用于查询。

public static class MyFunctions {
    [InjectLambda]
    public static bool IsAGoodProduct(Product product) {
        return product.Quality>3;
    }
    public static Expression<Func<Product,bool>> IsAGoodProduct() {
        return (p) => p.Quality>3;
    }
}

然后,实际查询可能看起来像预期的那样。

var goodProds = from p in dataContext.Products.ToInjectable()
                where p.IsAGoodProduct()
                select p;

ToInjectable调用创建一个轻量级代理,它用所需的lambda表达式替换IsAGoodProduct方法调用(如果相应地标记)。因此,您可以在查询中的任何位置使用扩展方法 - 参数化方法也可以。

答案 3 :(得分:1)

顺便说一下,我遇到了这个useful article,它解释了如何创建动态LINQ查询,使用自定义ToExpandable()扩展方法引用包装为表达式的函数。提供的解决方案可以在LINQ查询的各个部分中使用,同时保留comprehension syntax的使用,而不是使用lambda语法。