【问题标题】:Resolve ParameterExpression to actual Expression将 ParameterExpression 解析为实际的 Expression
【发布时间】:2013-01-01 14:23:36
【问题描述】:

我编写了一个 LINQ 提供程序,它运行良好,但有一个例外。它将 LINQ 查询转换为 ODATA-URL 标准。

如果我有以下 LINQ 语句:

.Select(x => x.Name.ToLower()).OrderByDescending(x => x)

当我用表达式访问者访问表达式树时,我会得到一个表达式部分 (OrderByDescending),它的类型是 ParameterExpression。

我现在的问题是:如何获得选定的 x.Name.ToLower() 表达式?这样我就可以将 orderBy 语句翻译成

$orderby=tolower(Name) desc

// 编辑:换句话说: 我有一个 ParameterExpression {x => x}。我希望将此表达式解析为 {x => x.Name.ToLower()}

【问题讨论】:

    标签: c# linq expressionvisitor


    【解决方案1】:

    你的代码有两个问题:

    1) 上面的 LINQ 表达式并不意味着 /Entities?$orderby=tolower(Name) desc。实际上没有办法将其转换为 OData。 LINQ 查询将获取所有实体,获取它们的 Name 属性并返回小写的字符串(名称)列表。它还会对列表进行排序(降序)。

    2) 此类表达式的表达式树如下所示:

    Call OrderBy
    - Argument 1 = Call Select
        - Argument 1 = Entities
        - Argument 2 = Lambda with parameter x(1)
           Body = ToLower(x(1).Name)
    - Argument 2 = Lambda with parameter x(2)
       Body = x(2)
    

    x(1) 和 x(2) 是 ParameterExpression 节点,它们表示 Select 和 OrderBy 调用中 lambda 的参数。 用 Select (ToLower(x(1).Name)) 的 lambda 的主体替换 x(2) 将不起作用。首先,该主体中有 x(1) 参数,这在第二个 lambda 的上下文中没有任何意义。其次,它会改变表达的含义。

    要获得 $orderby=tolower(Name) desc,输入的 LINQ 表达式必须类似于:

    Entities.OrderByDescending(x => x.Name.ToLower())
    

    【讨论】:

    • 那么就没有机会合并了吗?这很可悲,因为当我使用 .OrderByDescending(x => x.Name.ToLower()).Select(x => x.Name.ToLower()) 时,一切正常!
    • 您如何将其转换为 OData,它有同样的问题? OData 中没有构造可以让您执行 Select(x => x.Name.ToLower()) 的等效操作。可以合并,但您的访问者必须能够同时查看 OrderBy 和 Select 并将两者合并为一个操作。将这些作为单独的步骤处理是问题所在,因为您不能轻松地将 lambda 从一个转移到另一个(它们失去了意义)。
    猜你喜欢
    • 1970-01-01
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    相关资源
    最近更新 更多