简体   繁体   English

具有linq表达式的表达式树

[英]Expression tree with linq expressions

I have been playing with expression trees this week and I am wondering why this expression produces error when ran. 我这周一直在玩表达式树,我想知道为什么该表达式在运行时会产生错误。

var pe = Expression.Parameter(typeof(Nullable<DateTime>));

var ex = Expression.Lambda<Func<DateTime?, bool>>(
   (Expression<Func<DateTime?, bool>>) (x => x.HasValue), pe);

The idea behind this is to write expression trees with a mix of expression tree api and linq expressions. 这背后的想法是使用表达式树api和linq表达式混合编写表达式树。 It would make things easier to write for example instead of calling Expression.Property(...,..) I would just have x => x.Prop , right? 例如,这将使编写起来更容易,而不是调用Expression.Property(...,..)我将只有x => x.Prop ,对吗?

In my example instead of this Expression.Property(..hasvalue..) I would have this: x.HasValue . 在我的例子,而不是这个Expression.Property(..hasvalue..)我会有这样的: x.HasValue It would save me time on writing and it would look shorter, right? 这样可以节省我的写作时间,而且看起来更短,对吗?

The question is, is this possible? 问题是,这可能吗?

I guess I might be missing something about 我想我可能会缺少一些关于

Expression<Func<DateTime?, bool>> foo = x => x.HasValue (this works)

and

Func<DateTime?, bool> bar = x => x.HasValue (this works too)

What is happening behind those two? 这两个背后发生了什么? Are they the same? 他们是一样的吗?

Can linq expression be mixed with standard expression tree api??? LINQ表达式可以与标准表达式树API混合吗???

Please enlighten me on this, I feel lost. 请对此给予启发,我感到迷茫。 :) :)

This is a good question. 这是一个很好的问题。 Your two quotations 您的两个报价

Expression<Func<DateTime?, bool>> foo = x => x.HasValue

and

Func<DateTime?, bool> bar = x => x.HasValue

are examples of homoiconicity : the same symbol (in your case x => x.HasValue) stands for two very different objects. 同像性的例子:同一符号(在你的情况下,x => x.HasValue)代表两个非常不同的对象。 In the first case, it indicates an expression tree; 在第一种情况下,它表示一个表达式树。 in the second, a function. 第二,一个功能。 The former can be compiled down to the latter, but they are different types with different purposes. 前者可以简化为后者,但它们是具有不同用途的不同类型。 It is the declaration in your case that tells the compiler which version to go for. 您的情况下的声明会告诉编译器要使用哪个版本。 In the absence of this context, the compiler cannot read your mind and decides to bail out instead. 在没有此上下文的情况下,编译器无法理解您的想法,而是决定纾困。 That's why this won't compile: 这就是为什么它将无法编译的原因:

var bat = x => x.HasValue;

And that is why your statement won't compile. 这就是为什么您的陈述无法编译的原因。

Homoiconicity is what makes IQueryable and IEnumerable look so similar. 同质性使IQueryableIEnumerable看起来如此相似。 When you invoke 调用时

var filteredCollection = myCollection.Where(e => e.IsActive);

you are actually calling methods with a different signature depending on the type of filteredCollection (It's Func<MyClass, bool> for IEnumerable and Expression<Func<MyClass, bool>> for IQueryable ). 您实际上是根据filteredCollection的类型调用具有不同签名的方法(对于IEnumerableFunc<MyClass, bool> ,对于IQueryable Expression<Func<MyClass, bool>> )。

Regarding your specific situation, you can't achieve what you want to do directly, but if you write a sneaky extension method: 关于您的具体情况,您无法直接实现您想做的事情,但是如果您编写了一个偷偷摸摸的扩展方法:

public static class ExpressionExtensions
{
    public static Expression<Func<T, TProperty>> Lambda<T, TProperty>(this ParameterExpression pe, Expression<Func<T, TProperty>> property)
    {
        return Expression.Lambda<Func<T, TProperty>>(property, pe);
    }
}

then you can do this: 那么您可以执行以下操作:

var pe = Expression.Parameter(typeof(DateTime?));
var ex = pe.Lambda<DateTime?, bool>(x => x.HasValue);

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

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