c# - 如何为 Contains<T> 构建表达式树

标签 c# linq expression-trees

我正在关注这个 SO answer将 lambda 表达式转换为部分 SQL 语法。

但是,我在解析 Contains 的表达式时遇到问题。我添加了一个方法:

private bool ParseContainsExpression(MethodCallExpression expression)
{
    MemberExpression member = (MemberExpression)expression.Arguments[0];

    var methodInfo = typeof(List<int>).GetMethod("Contains", new Type[] { typeof(int) });

    //TODO check if list contains value

    return false;
}

由于我对表达式完全陌生,我不知道从哪里获取属性名称和值,以及包含我要检查的值的列表。这些属性和值存储在表达式中的什么位置?

最佳答案

您的实现与示例答案完全不同。您确实需要从 ExpressionVisitor 继承,以便您可以正确地解析树。

让我们以这个表达式为例:

var myList = new List<string> { "A" };
Expression<Func<string, bool>> a = (s) => myList.Contains(s);
ParseContainsExpression(a.Body as MethodCallExpression);

private bool ParseContainsExpression(MethodCallExpression expression)
{
    expression.Object; //myList
    expression.Arguments[0]; //s    
    return false;
}

但是请注意,这些仍然是表达式,它们还不是实际值。您需要调用表达式来获取值。

但是,在我们的例子中 - myList 实际上是一个 ConstantExpression。所以我们可以这样做:

((expression.Object as MemberExpression).Expression as ConstantExpression).Value; //myList

返回原始列表。请注意,这是一个 field 访问,因为表达式被编译成一个闭包,它将 myList 作为闭包类中的一个字段。如您所见,我们必须对正在处理的表达式类型做出很多假设(它是一个字段访问,然后是一个常量表达式)。您确实需要一个成熟的访问者实现才能正确执行此操作(链接的答案描述了这一点)

关于c# - 如何为 Contains<T> 构建表达式树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36713101/

相关文章:

c# - 有没有更好的方法来编写业务逻辑来验证互斥代码?

linq - 将 GroupBy 动态添加到 Lambda 表达式

c# - 什么更快 : expression trees or manually emitting IL

c# - 表达式转换

C#极小极大树的实现

c# - C# 中的非托管句柄,我需要释放还是销毁?

c# - 从 ISampleGrabber 获取字符串并以第一种形式更新文本框

c# - OrderBy 子集合特定类别

c# - 自定义 Nullable<T> 扩展方法和 SelectMany

c# - 从列表中获取请求的列不同值