【问题标题】:How can I reuse expressions within LINQ statements?如何在 LINQ 语句中重用表达式?
【发布时间】:2009-06-12 14:18:25
【问题描述】:

出于 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 的限制?

【问题讨论】:

    标签: c# linq lambda


    【解决方案1】:

    如果您从 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()};
    

    【讨论】:

    • @Gary -- 希望您不介意我添加了一个示例以使其更清晰。
    • 如何使用:"where IsAGoodProduct().Compile().Invoke()"
    • @Razzie,不,那是行不通的——首先,它需要一个 表达式树(因为它是一个数据上下文)——而不是一个委托。其次,调用根本不能那样使用。
    • @Marc 好的,谢谢,我测试了它,但使用 List 并且它在那里工作,所以我想知道。
    【解决方案2】:

    我遇到了同样的问题,并希望保留在查询语法中使用扩展方法的能力(与普通支持的函数一样......)。一个解决方案可能是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 调用创建一个轻量级代理,它将IsAGoodProduct 方法调用(如果有相应标记)替换为所需的 lambda 表达式。因此,您可以在查询中的任何位置使用扩展方法——参数化方法也可以。

    【讨论】:

    • 你创建了这个库吗?在这里陈述可能是个好主意。
    • 我的第一句话应该说:“我 [...] 想要保留 [...]”。由于英语不是我的母语,因此可能不如预期的那么清晰。我将编辑我的帖子以进一步澄清。
    【解决方案3】:

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

    找到文章here

    您可以将用于投影重用的程序集作为nuget package 获取,源位于CodePlex

    您的帖子已经过去了一段时间。我希望它仍然对你有帮助。如果没有,也许对于其他阅读此主题的人。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-03
        相关资源
        最近更新 更多