我在我的代码中有一个Func<TCollection, T>
,用于选择特定的属性。
在调用另一个方法时,我需要将Expression<Func<TCollection, T>>
作为参数。
是否有办法将Func<TCollection, T>
转换(或创建)为Expression<Func<TCollection, T>>
?
谢谢
你无法基于方法重建表达式,因为表达式需要知道原始语句而不是IL。但是,你可以创建一个表达式,其中调用了你的函数,例如:
Func<int> func = () => 1;
Expression<Func<int>> expression = Expression.Lambda<Func<int>>(Expression.Call(func.Method));
需要注意的是,像EF这样的系统无法真正处理这种情况。
虽然你可以创建一个调用委托的表达式树,但这很可能没有什么用 - 因为对于分析表达式树的代码来说,委托基本上是一个黑匣子。假设你想使用类似于LINQ to SQL这样的东西,查询分析器需要能够查看你的逻辑以将其转换为SQL - 如果它到达一个普通的委托,那么它就无法完成这项工作。
你应该改变首次创建委托的代码,改为创建一个表达式树。
你可以像这样做:
Func<object, string> func = a => a.ToString();
Expression<Func<object, string>> expr = a => func(a);
但是你只会得到包含原始Func方法调用的表达式,而无法分析Func本身的内容。
Func<TCollection, T>
到Expression<Func<TCollection, T>>
)中创建表达式,但您可以做相反的操作。
也就是说,通过编译它(.compile
),将Expression<Func<TCollection, T>>
转换为Func<TCollection, T>
。
因此,如果您需要两者,可以在函数中使用表达式,并在提供的集合对象上编译和执行它们。
当然,我们必须注意编译表达式会很慢。
public class GenericFilter<T> where T : class, new()
{
public Expression<Func<T, bool>> Filter = item => true;
}
用法;
var filter=new GenericFilter<blabla>().Filter.And(x=>...);
filter=filter.And(x=>...);