【问题标题】:Identify parentheses in lambda expression with ExpressionVisitor in C#在 C# 中使用 ExpressionVisitor 识别 lambda 表达式中的括号
【发布时间】:2014-07-18 19:21:26
【问题描述】:

我有一个库,它使用 ExpressionVisitor 类将 lambda 表达式转换为 odata 过滤器字符串。 例如,表达式o => o.Teste == null && !(o.Date != DateTime.Now) 变成$filter=Teste eq null and not(Date ne xx/xx/xx)

它工作正常。问题是当我必须用括号 () 对部分条件进行分组时。括号被忽略,它只写没有它的条件。 例如,表达式(o => o.Name != null && o.Name == "Joe") || !(o.Date != DateTime.Now) 变成$filter=Name ne null and Name eq 'Joe' or not(Date ne xx/xx/xx)

奇怪的是ExpessionVisitor 似乎没有识别括号,它有一个NodeType,而不是!(expression),但它没有(expression)

我在 Google 上搜索了两天,但似乎找不到答案。

提前感谢您的帮助。

【问题讨论】:

    标签: c# lambda expression expressionvisitor


    【解决方案1】:

    not 的节点类型不适用于 !(expression),它仅适用于 !expression - 括号不是其中的一部分。

    源代码中需要括号来指示您想要的优先级。它们在表达式树中不是必需的,因为优先级是树中固有的。

    如果您不介意有时有额外的括号,您可以让您的字符串转换始终包含它们。因此,每当您有一个带有操作数表达式xy 的OR 或和AND 表达式时,只需将其转换为(x || y)(x && y),无条件地包括这些括号。它可能看起来不漂亮,但它总是会给你正确的优先级。

    【讨论】:

    • 感谢您的回答。但是如果我总是把括号放在我有||或 && 它可能会弄乱过滤器的处理方式。它会忽略我明确添加到表达式中的括号。
    • @Eric.M:我希望它不会弄乱过滤器的处理方式。我不确定您所说的“忽略我明确添加到表达式中的括号”是什么意思 - 编译器 将使用它们来确定如何创建表达式树以开始。你有没有尝试过这个并发现它不起作用?
    • o => o.A == "A" || (o.X == "X" && x.Y == "Y") 这样的表达式会变成((A eq 'A') || ((X eq 'X') && (Y eq 'Y')))((A eq 'A') || (X eq 'X')) && (Y eq 'Y')?。因为第一个是正确的。这很可怕,但它会起作用。我实际上想识别括号并在必要时添加它们,这样会好很多。
    • 而且,因为它是 odata 并且它作为 Url 中的参数,如果我可以有更少的字符,那就更好了,因为过滤器可能很长,我不想添加预订到网址。
    • @Eric.M:我希望它会变成第一个 - 你不能只是测试它吗?如果要减少字符数,则需要编写代码来确定不带括号的表示是否与带括号的表示相同。这可能是相当多的工作......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2012-09-15
    • 2010-10-05
    相关资源
    最近更新 更多