如何在LINQ查询提供程序(ExpressionVisitor)中调用函数或属性

时间:2018-04-27 12:32:44

标签: .net linq expressionvisitor

我正在创建一个LINQ Provider。查询可能如下所示:

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

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

解析表达式树时,我得到表达式转换(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转换为Unary,我可以将其视为Convert(DateTime.Now)。 我需要以某种方式调用DateTime.Now属性,以便稍后可以在SQL查询中添加它。 像这样:

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

我无法弄清楚如何调用属性:(

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

1 个答案:

答案 0 :(得分:1)

这是一个帮助扩展方法,用于评估Expression以获取它们的值 - 您必须指定返回类型,因为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();
}