2012-02-21 76 views
31

我的代码中有一个Func<TCollection, T>。我用它来选择某些属性。从Func创建表达式

在另一个方法的调用我需要Expression<Func<TCollection, T>>作为参数。

有什么办法转换(或创建)Func<TCollection, T>Expression<Func<TCollection, T>>

感谢

回答

30

因为表达需要知道原来的陈述,而不是IL无法重新创建基于一个方法的表达式。但是,您可以创建一个Expresson这使得一个方法调用你的FUNC,如:但是

Func<int> func =() => 1; 
Expression<Func<int>> expression = Expression.Lambda<Func<int>>(Expression.Call(func.Method)); 

注意,像EF系统不能真正与这个

+2

假设你*能*获得IL,不过,你可以反编译的IL,如反射和ILSpy做。 (当然,不能保证这与编译IL的代码完全相同。)有没有办法获得代理的IL? – phoog 2012-02-21 14:37:05

+5

我想你可能需要在你的调用中添加func.Target。 我试过这个更复杂的Func <>,它抱怨我试图用空对象调用实例方法。 我将它改为Expression.Call(Expression.Constant(func.Target),func.Method,args)并且一切都很好 – ben 2014-03-13 16:35:49

25

工作,而你可以只是创建一个表达式树它调用了你的委托,它不太可能是有用的 - 因为就分析表达式树的代码而言,委托基本上是一个黑盒子。假设您尝试使用LINQ to SQL之类的东西,查询分析器将需要能够对您的逻辑进行转换以将其转换为SQL - 并且如果它到达普通的委托,则不能这样做。

你或许应该改变其在首位的代表出现的代码,而不是创建一个表达式树。

7

你可以做这样的事情:

Func<object, string> func = a => a.ToString(); 
Expression<Func<object, string>> expr = a => func(a); 

但你只会得到包含您的方法调用原来的函数功能的表达式。你将无法分析func本身的内容。

+4

但是Skeet先生自然会说它比我好得多! :-) – Simon 2012-02-21 12:36:38

9

您无法从委托人创建表达式(从Func<TCollection, T>Expression<Func<TCollection, T>>),但您可以进行相反的操作。

也就是说,通过编译将Expression<Func<TCollection, T>>转换为Func<TCollection, T>.compile)。

所以,如果你需要他们两个,你可以在你的函数使用表达式和的情况下,你需要它,编译和执行他们设置的回收对象。

我们必须要注意的课程,编写一个表达式是缓慢的。

+0

谢谢,救了我;( – Akbari 2017-05-01 04:10:38

+0

这正是我所需要的,只是试图减少重复的代码,似乎我是从错误的方式看待它的 – 2017-07-06 10:32:44

相关问题