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

26

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

例如:

我有:

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个回答

24

如果你不使用 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
@Gary -- 希望你不介意我加了一个示例来使它更清晰。 - tvanfosson
使用以下代码怎么样:“where IsAGoodProduct().Compile().Invoke()” - Razzie
@Razzie,不行 - 首先,它需要一个表达式树(因为它是数据上下文)- 而不是委托。其次,Invoke不能像那样使用。 - Marc Gravell
@Marc 好的,谢谢。我测试了一下,但是使用List<T>时可以工作,所以我有点疑惑。 - Razzie

5
我曾经遇到相同的问题,希望能在查询语法中保留使用扩展方法的能力(就像普通支持的函数一样...)。解决方案可能是使用这个库(剧透:我是作者)。
你只需要实现该方法两次,一次用于常规使用,一次用于查询。
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;
< p > ToInjectable 调用创建了一个轻量级代理,它将标记正确的 IsAGoodProduct 方法调用替换为所需的lambda表达式。 因此,您可以在查询中的任何地方使用扩展方法-参数化方法也可以工作。


你创建了这个库吗?在这里声明一下可能是个好主意。 - Seva
1
我的第一句话应该是:“我[...]想要保留[...]”。由于英语不是我的母语,可能不够清晰明了。我会编辑我的帖子以进一步澄清。 - Axel Heer

3
我们遇到了同样的问题。它不支持开箱即用,这对于LOB应用程序是一个重大问题。我最终撰写了一篇关于LINQ表达式重用的代码项目文章,包括一个名为 LinqExpressionPrjection 的非常小的实用程序,可在投影中实现重用(包括匿名类型)。
在此处找到该文章:链接
您可以获取用于投影重用的程序集 NuGet包,源代码在 CodePlex 上。
自您发布帖子以来已经过了一段时间。我希望它仍然对您有所帮助。如果不是,也许对于阅读此线程的其他人有帮助。

1
顺便说一下,我发现了这篇有用的文章,它解释了如何使用自定义ToExpandable()扩展方法创建引用作为表达式包装的函数的动态LINQ查询。提供的解决方案可以在LINQ查询的各个部分中使用,同时保留对理解语法的使用,而不是诉诸于lambda语法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接