I get different behaviours when calling Expression.GreaterThanOrEqual
dynamically or directly.
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace ExpressionExample
{
class Program
{
static void Main(string[] args)
{
// Build expression head.
ParameterExpression param = Expression.Parameter(typeof(MyObj), "x");
MemberExpression property = Expression.Property(param, "MyProperty");
int value = 1;
// Build expression body.
MethodInfo greaterThanOrEqual = typeof(Expression)
.GetMethod("GreaterThanOrEqual",
new[] { typeof(Expression), typeof(Expression) });
Expression valueExpr = Expression.Convert(Expression.Constant(value),
property.Type);
// Dynamic Call
//var expressionBody = Expression.Call(null, greaterThanOrEqual, property,
valueExpr);
// Direct Call
var expressionBody = Expression.GreaterThanOrEqual(property, valueExpr);
// Make Lambda.
Expression.Lambda<Func<MyObj, bool>>(expressionBody, param);
}
}
class MyObj
{
public int MyProperty { get; set; }
}
}
I took the code out of context for simplicity reasons. The Lambda at the end is later used within a where method of a Queryable
. The direct call works fine and gives expected results. The dynamic call however throws a System.ArgumentException
saying that System.Int32
cannot be used as a parameter for the BinaryExpression
GreaterThanOrEqual. That's actually the reason why I convert the value previously, which is also necessary for the direct call.
What's the difference here? How could I get the dynamic call to work?
I still don't understand the practical usage (hence the need) of your request, so just answering your concrete questions.
Whats the difference here?
The difference is that Expression.Call
does not really call the method, but creates a MethodCallExpression
which represents a call to method inside the expression tree. Thus it's not supposed to be used to invoke other Expression
builder methods.
How could I get the dynamic call to work?
Instead of Expression.Call
, you need to simply invoke the methof via reflection:
// Dynamic Call
var expressionBody = (Expression)greaterThanOrEqual.Invoke(
null, new object[] { property, valueExpr });