首页 > 解决方案 > 如何在 LINQ 查询提供程序 (ExpressionVisitor) 中调用函数或属性

问题描述

我正在创建一个 LINQ 提供程序。查询可能如下所示:

customers.Where( (f) => f.Date < DateTime.Now )

在我的查询提供程序中,我执行一个 ExpressionVisitor,它读取查询并创建 MSSQL 查询。但是当我访问 ExpressionTree 时,我无法找到如何调用 DateTime.Now 属性。

解析表达式树时,我得到表达式转换(日期时间。现在)。我想以某种方式调用该属性。所以我稍后可以将它附加到生成的 sql 查询中。上面我有 C# 语法中的查询,尽管我在 VB.NET 中编写代码。代码如下:

 Protected Overrides Function VisitBinary(expr As BinaryExpression) As Expression
    expr = ETH.ConvertVBStringCompare(expr)

    If (expr.Right.NodeType = ExpressionType.Convert) Then
        Dim a = ETH.CallIt(expr)
    End If

它的作用是当我 Expression.Right.NodeType 是 ExpresionType.Convert 我步入一个帮助类:

Friend Shared Function CallIt(ByVal exp As BinaryExpression) As BinaryExpression

    If exp.Left.NodeType = ExpressionType.MemberAccess Then
        Dim compare = CType(exp.Left, MemberExpression)
        Dim compare1 = CType(exp.Right, UnaryExpression)

当我检查 BinaryExpression 时,我可以在左侧看到 f.Date。如果我将 exp.Right 转换为一元,我可以将其视为 Convert(DateTime.Now)。我需要以某种方式调用 DateTime.Now 属性,以便稍后在 SQL 查询中附加它。像这样:

select * from customers where Date < "2018-05..."

我只是不知道如何调用该属性:(

更新: 好的,所以我发现用于创建 LINQ 提供程序的msdn 文章有一个帮助程序类的示例,一个部分评估程序,它可以为您完成这项工作。它通过表达式树并评估函数调用等。所以我现在在我的项目中使用该类。它更容易,完成后它会返回表达式树。

标签: .netlinqexpressionvisitor

解决方案


这是一个辅助扩展方法,用于评估Expressions 以获取其值 - 您必须指定返回类型,因为Expression没有返回类型。

public static T Evaluate<T>(this Expression e) {
    //A little optimization for constant expressions
    if (e.NodeType == ExpressionType.Constant)
        return (T)((ConstantExpression)e).Value;
    else
        return (T)Expression.Lambda(e).Compile().DynamicInvoke();
}

推荐阅读