我编写了一些带Expression
的代码,并充当代理来进行某些调用。使这项工作的主要代码就是这样
private static IEnumerable<object> GetArguments(MethodCallExpression body)
{
IEnumerable<object> arguments =
body.Arguments.Select(
expression =>
{
MemberExpression member = expression as MemberExpression;
return ((dynamic) member.Member).GetValue(((ConstantExpression) member.Expression).Value);
});
return arguments;
}
这将获取Expression
中存在的参数值,并将其返回IEnumerable
。这是我在最初消费的项目中写的时候得到的行为,我可以看到正确输出的结果参数值。我甚至把它移到测试床项目来测试代码,它也在那里工作得很好。但是,当我将.cs文件放在另一个项目中,更新名称空间并引用它以便能够广泛使用它时,我会得到例外情况,例如
System.InvalidCastException:无法将类型为“System.Linq.Expressions.PropertyExpression”的对象强制转换为“System.Linq.Expressions.ConstantExpression”。
我甚至无法使用我的申请。
我已将我的提取回到“它在本地工作”状态,以确保它实际上是有效的,并且确实如此。但是,我注意到我的日志记录中仍然有一些例外,即使它没有像我在项目外部那样呕吐。尽管如此,我仍然可以使用我的应用程序。
重复移动到外部项目并通过引用使用它会重新引入这些错误,我甚至无法使用我的应用程序。
新问题:我该如何处理PropertyExpression
?它们没有公开Value
属性并且是内部属性所以我没有演员和检查。 MemberExpression
也没有Value
属性。
答案 0 :(得分:1)
最简单的解决方案是不依赖于表达式的形状,让表达式树库通过构建#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *runner(void *param);
int main(int argc, char *argv[])
{
...
然后在其上使用Compile()
并执行来评估每个子表达式返回的代表:
LambdaExpression
请注意,编译每个子表达式需要一些时间,因此这种方法会相对较慢。
答案 1 :(得分:0)
您应该评估表达式而不是依赖它的形状。最简单的方法是调用.Compile().Invoke()
,但这很慢并且会造成内存泄漏。您可以通过解释表达式(通过访问者递归遍历它并手动执行其中的操作)或缓存编译结果来避免这种情况。我写了一个可以同时执行这两个工作的库,速度很快并且在生产中使用了很长时间了:https://github.com/Miaplaza/expression-utils