动态或直接调用Expression.GreaterThanOrEqual
时,我会遇到不同的行为。
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; }
}
}
出于简单原因,我将代码脱离了上下文。最后的Lambda稍后在Queryable
的where方法中使用。直接调用工作正常,并给出预期的结果。但是,动态调用会引发System.ArgumentException
说System.Int32
不能用作BinaryExpression
GreaterThanOrEqual的参数。这实际上是我之前转换该值的原因,这也是直接调用所必需的。
这里的区别是什么?我怎么能让动态调用工作?
答案 0 :(得分:3)
我仍然不了解您的请求的实际用法(因此需要),所以只回答您的具体问题。
这里的区别是什么?
不同之处在于Expression.Call
并没有真正调用该方法,而是创建了一个MethodCallExpression
,其中表示对表达式树内方法的调用。因此,它不应该用于调用其他Expression
构建器方法。
我怎样才能让动态调用工作?
而不是Expression.Call
,您需要通过反射简单地调用methof:
// Dynamic Call
var expressionBody = (Expression)greaterThanOrEqual.Invoke(
null, new object[] { property, valueExpr });