当类在其他项目中时,获取表达式值会中断

时间:2016-01-22 18:20:30

标签: c# .net linq linq-expressions

我编写了一些带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属性。

2 个答案:

答案 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