从Func创建表达式

Sol*_*arX 38 c# generics

Func<TCollection, T>我的代码中有一个.我用它来选择某些属性.

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

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

谢谢

Pol*_*ity 40

您无法基于方法重新创建表达式,因为表达式需要知道原始语句,而不是IL.但是,你可以创建一个Expresson,它可以调用你的func方法:

Func<int> func = () => 1;
Expression<Func<int>> expression = Expression.Lambda<Func<int>>(Expression.Call(func.Method));
Run Code Online (Sandbox Code Playgroud)

但请注意,像EF这样的系统无法真正解决这个问题

  • 我想你可能需要在你的通话中添加func.Target.我尝试使用更复杂的Func <>并且它抱怨我试图用null对象调用实例方法.我把它改成了Expression.Call(Expression.Constant(func.Target),func.Method,args),一切都很好 (6认同)
  • 假设你*可以*得到IL,你可以反编译IL,就像Reflector和ILSpy那样.(当然,不能保证这与编译IL的代码完全相同.)有没有办法获得委托的IL? (2认同)

Jon*_*eet 31

虽然你可以创建一个调用你的委托的表达式树,但它不太可能有用 - 因为就分析表达式树的代码而言,委托基本上是一个黑盒子.假设您正在尝试使用LINQ to SQL之类的东西,查询分析器将需要能够查看您的逻辑以将其转换为SQL - 如果它到达普通委托,则无法执行此操作.

您可能应该首先更改委托中提供的代码,以创建表达式树.


Sim*_*mon 14

你可以这样做:

Func<object, string> func = a => a.ToString();
Expression<Func<object, string>> expr = a => func(a);
Run Code Online (Sandbox Code Playgroud)

但是你只会得到一个包含对原始Func的方法调用的表达式.您将无法分析func本身的包含.

  • 但Skeet先生自然会比我好得多!:-) (4认同)
  • 你这么说,但你的答案是我在晚上往返机场后的第二天早上对我有意义的答案......非常简洁地重申了一个想法,即 func 是可以被调用的东西,是一个表达式是对 func 的调用。 (2认同)

Geo*_*kis 9

你不能(从创建委托的表达式Func<TCollection, T>Expression<Func<TCollection, T>>),但你可以做oposite.

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

因此,如果您需要它们,您可以在函数中使用表达式,以备需要时,在提供的集合对象上编译和执行它们.

我们必须注意编译表达式的速度很慢.