表达式等于
所以,我正在尝试找出表达式树。我试图添加动态等于可查询,其中 T 是几个不同的表之一。我首先检查表中是否包含我想要过滤的字段。
ParameterExpression param = Expression.Parameter(typeof(TSource), "x");
Expression conversionExpression = Expression.Convert(Expression.Property(param, _sourceProperty), typeof(TList));
Expression<Func<TSource, TList>> propertyExpression = Expression.Lambda<Func<TSource, TList>>(conversionExpression, param);
Expression<Func<TList, TList, bool>> methodExpression = (x, y) => x.Equals(y);
ReadOnlyCollection<ParameterExpression> parameters = propertyExpression.Parameters;
InvocationExpression getFieldPropertyExpression = Expression.Invoke(
propertyExpression,
parameters.Cast<Expression>());
MethodCallExpression methodBody = methodExpression.Body as MethodCallExpression;
MethodCallExpression methodCall = Expression.Call(methodBody.Method, Expression.Constant(equalTo), getFieldPropertyExpression);
Expression<Func<TSource, bool>> equalsStatement = Expression.Lambda<Func<TSource, bool>>(methodCall, parameters);
return source.Where(equalsStatement);
当我执行此操作时,我在 Call 语句中遇到 MethodInfo 问题。它告诉我;
静态方法需要空实例,非静态方法需要非空实例。
我不是表达式树的大师,但我想我了解我在这里所做的大约 75%,并且知道我想要实现的目标。 TList 现在是一个不好的名字,但我从一个可以很好地生成 In 语句的示例中获取了这个名称。
我真的在这里寻找一个解释,以便我可以自己完成代码,或者一个解释我所缺少内容的解决方案。
编辑:
好的,所以在经历了一个非常令人沮丧的下午之后,仍然感觉我不太完全理解我所看到的内容,我想我有一个答案。
ParameterExpression sourceObject = Expression.Parameter(typeof(TSource), "x");
Expression<Func<TSource, bool>> check = Expression.Lambda<Func<TSource, bool>>
(
Expression.Equal(
Expression.MakeMemberAccess(sourceObject, typeof(TSource).GetProperty(_sourceProperty)),
Expression.Constant(equalTo)
),
sourceObject
);
return source.Where(check);
有人能向我解释为什么原版不适合我想做的事情吗?我想更多地了解实际过程,但我觉得我没有像我希望的那样快地掌握它。
So, I'm trying to figure out Expression trees. I'm trying to add in a dynamic equals to a Queryable where T is one of several different tables. I'm first checking the table contains the field I want to filter on.
ParameterExpression param = Expression.Parameter(typeof(TSource), "x");
Expression conversionExpression = Expression.Convert(Expression.Property(param, _sourceProperty), typeof(TList));
Expression<Func<TSource, TList>> propertyExpression = Expression.Lambda<Func<TSource, TList>>(conversionExpression, param);
Expression<Func<TList, TList, bool>> methodExpression = (x, y) => x.Equals(y);
ReadOnlyCollection<ParameterExpression> parameters = propertyExpression.Parameters;
InvocationExpression getFieldPropertyExpression = Expression.Invoke(
propertyExpression,
parameters.Cast<Expression>());
MethodCallExpression methodBody = methodExpression.Body as MethodCallExpression;
MethodCallExpression methodCall = Expression.Call(methodBody.Method, Expression.Constant(equalTo), getFieldPropertyExpression);
Expression<Func<TSource, bool>> equalsStatement = Expression.Lambda<Func<TSource, bool>>(methodCall, parameters);
return source.Where(equalsStatement);
When I execute this, I get an issue with the MethodInfo in the Call statement. It tells me;
Static method requires null instance, non-static method requires non-null instance.
I'm no master of Expression trees, but I think I understand about 75% of what I'm doing here and know what I'm trying to achieve. The TList is a bad name right now, but I took this from an example that works to produce an In statement just fine.
I'm really looking for an explanation here so I can work through the code myself, or a solution with an explanation of what I was missing.
Edit:
Ok, so after a very frustrating afternoon and still not quite feeling like I understand what I'm looking at entirely, I think I have an answer.
ParameterExpression sourceObject = Expression.Parameter(typeof(TSource), "x");
Expression<Func<TSource, bool>> check = Expression.Lambda<Func<TSource, bool>>
(
Expression.Equal(
Expression.MakeMemberAccess(sourceObject, typeof(TSource).GetProperty(_sourceProperty)),
Expression.Constant(equalTo)
),
sourceObject
);
return source.Where(check);
Is anybody able to explain to me why the original just wasn't fit for what I was trying to do? I want to understand more about the actual process, but I feel I'm not picking it up as fast as I would like.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Expression.Call 有两组重载(每组都有很多重载)。一组用于实例方法,另一组用于静态方法。在静态方法中,第一个参数是 MethodInfo 对象 - 就像您所拥有的一样。对于实例方法,第一个参数应该是表示目标的表达式(即方法调用中“.”的左侧。)鉴于您收到的错误,听起来像MethodInfo 表示一个非静态方法,因此您必须提供一个表示实例的表达式作为第一个参数。
Expression.Call has two sets of overloads (with lots of overloads in each). One set is for instance methods and the other set is for static methods. In those for static methods, the first argument is a MethodInfo object -- exactly like you have. For instance methods, the first argument should be an Expression representing the target (i.e. the left-hand-side of the "." in a method call.) Given the error you are receiving, it sounds like the MethodInfo represents a non-static method, and therefore you must provide an expression representing the instance as the first argument.