我的代码中有Func<TCollection, T>
。我用它来选择某些属性。
在调用另一种方法时,我需要Expression<Func<TCollection, T>>
作为参数。
有没有办法将Func<TCollection, T>
转换(或创建)到Expression<Func<TCollection, T>>
?
感谢名单
答案 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
。
因此,如果你需要它们,你可以在你的函数中使用表达式,以备你需要它时,在提供的集合对象上编译和执行它们。
我们必须注意编译表达式的速度很慢。