从Func创建表达式

时间:2012-02-21 12:28:00

标签: c# generics

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

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

有没有办法将Func<TCollection, T>转换(或创建)到Expression<Func<TCollection, T>>

感谢名单

4 个答案:

答案 0 :(得分:36)

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

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

但请注意,像EF这样的系统无法真正使用此

答案 1 :(得分:27)

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

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

答案 2 :(得分:10)

您可以这样做:

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

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

答案 3 :(得分:9)

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

即,通过编译Expression<Func<TCollection, T>>Func<TCollection, T>转换为.compile

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

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