I am creating a LINQ Provider. And the query could look like this:
customers.Where( (f) => f.Date < DateTime.Now )
In my Query provider I Execute an ExpressionVisitor that reads the query and creates MSSQL queries. But I cannot find out how to Invoke the DateTime.Now property, when I am visiting the ExpressionTree.
When parsing the expressiontree I get the Expression Convert(Datetime.Now). I want to somehow call that property. So I later can append it to the generated sql query. Above I had the query in C# syntax, although I code in VB.NET. The code is as below:
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
What it does is when I Expression.Right.NodeType is ExpresionType.Convert I step into an helper class:
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)
When I inspect the BinaryExpression I can see the f.Date on the Left side. And If I convert the exp.Right to Unary I can see it as an Convert(DateTime.Now). I need to invoke the DateTime.Now property somehow so I can append it later in the SQL Query. Like this:
select * from customers where Date < "2018-05..."
I just cannot figure out how to invoke the property :(
UPDATE: Okey, so I found out that the msdn article for creating an LINQ Provider has an example of an helper Class, a partial evaluator, that does this job for you. It goes trough the expression tree and evaluates function calls etc. So I use that class in my project now. It's easier and it returns the Expression tree when it's done.
Here is a helper extension method for evaluating Expression
s to get their value - you have to specify the return type since Expression
doesn't have one.
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();
}