简体   繁体   English

从 Func 创建表达式

[英]Create Expression from Func

I have a Func<TCollection, T> in my code.我的代码中有一个Func<TCollection, T> I use it to select certain properties.我用它来选择某些属性。

In a call to another method I need Expression<Func<TCollection, T>> as a parameter.在调用另一种方法时,我需要Expression<Func<TCollection, T>>作为参数。

Is there any way to convert (or create from) Func<TCollection, T> to Expression<Func<TCollection, T>> ?有什么方法可以将Func<TCollection, T>转换(或创建)为Expression<Func<TCollection, T>>

Thanx谢谢

You can not recreate an expression based on a method since an expression needs to know the original statements, not IL.您不能基于方法重新创建表达式,因为表达式需要知道原始语句,而不是 IL。 You can however create an Expresson which makes a method call to your func like:但是,您可以创建一个 Expresson,对您的 func 进行方法调用,例如:

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

Note however that systems like EF can't really work with this但是请注意,像 EF 这样的系统不能真正使用它

While you could just create an expression tree which calls your delegate, it's unlikely to be useful - because the delegate will basically be a black box as far as the code analyzing the expression tree is concerned.虽然您可以只创建一个调用您的委托的表达式树,但这不太可能有用 - 因为就分析表达式树的代码而言,委托基本上是一个黑盒子。 Assuming you're trying to use something like LINQ to SQL, the query analyzer will need to be able to peer into your logic to convert it to SQL - and it can't do that if it reaches a plain delegate.假设您尝试使用 LINQ to SQL 之类的东西,查询分析器将需要能够窥探您的逻辑以将其转换为 SQL - 如果它到达普通委托,它就无法做到这一点。

You should probably change the code which comes up with the delegate in the first place, to create an expression tree instead.您可能应该首先更改委托提供的代码,以创建一个表达式树。

You can do something like this:你可以这样做:

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

But you will only get an expression containing your method call to the original Func.但是您只会得到一个表达式,其中包含您对原始 Func 的方法调用。 You won't be able to analyse the contains of the func itself.您将无法分析 func 本身的包含。

You cannot create an expression from a delegate (from Func<TCollection, T> to Expression<Func<TCollection, T>> ) but you can do the oposite.您不能从委托创建表达式(从Func<TCollection, T>Expression<Func<TCollection, T>> ),但您可以做相反的事情。

That is, convert a Expression<Func<TCollection, T>> to a Func<TCollection, T> by compiling it ( .compile ).也就是说,通过编译 ( .compile ) 将Expression<Func<TCollection, T>>转换为Func<TCollection, T>

So, if you need both of them you can use expressions at your functions and in case you need it, compile and execute them on a provided collection object.因此,如果您同时需要它们,您可以在函数中使用表达式,如果需要,在提供的集合对象上编译并执行它们。

We have to note of course that compiling an expression is slow.当然,我们必须注意编译表达式很慢。

Create a class like below;创建一个如下所示的类;

 public class GenericFilter<T> where T : class, new()
    {
        public Expression<Func<T, bool>> Filter = item => true;

    }

Usage;用法;

var filter=new GenericFilter<blabla>().Filter.And(x=>...);
filter=filter.And(x=>...);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM