5
One way you can now do this is to take advantage of the fact that F# will perform this conversion automatically when invoking methods on .NET types that expect a Expression>
.
现在可以这样做的一种方法是利用f#将在调用. net类型的方法时自动执行此转换,而这种方法期望表达式
>。
I'm not entirely sure when this got added to the language, but certainly with F# 4, you don't need to explicitly convert F# expressions into LINQ ones. If the reason you wanted to do this in the first place was to be able to use IQueryable
LINQ APIs (or other expression-based .NET APIs) then it now just works with no effort, e.g.:
我不完全确定这是什么时候添加到语言中,但是在f# 4中,您不需要显式地将f#表达式转换为LINQ。如果您想要这样做的原因是能够使用IQueryable LINQ api(或其他基于expressnet的. net api),那么现在它就可以不费力地工作了,例如:
someEfDataContext.MyEntities.Single(fun e -> e.Id = 42)
just works. Even though this looks like an ordinary lambda (we've not used F#'s expression syntax), this compiles to code that produces an F# expression object, and then passes that to LeafExpressionConverter.QuotationToExpression
to turn it into a LINQ expression object.
只是工作。即使这看起来像一个普通的λ(我们没有使用f#表达式语法),这种编译代码,产生一个f#表达式对象,然后将LeafExpressionConverter。QuotationToExpressi,把它变成一个LINQ表达式对象。
But sometimes you'll want to get hold of the LINQ-style expression object directly in F#. (E.g., sometimes it's useful to write an F# function that produces an expression that you'll use in multiple queries.) In that case you can write a helper like this:
但有时您会希望直接在f#中获得linqstyle表达式对象。(例如,有时编写一个f#函数来生成一个在多个查询中使用的表达式是很有用的。)在这种情况下,你可以这样写一个帮手:
type FunAs() =
static member LinqExpression<'T, 'TResult>(e: Expression>) = e
This looks like it does nothing - it just returns its argument. However, because FunAs
is a .NET type, F# will automatically compile any call site that invokes this with a fun
expression into code that generates a suitable LINQ query expression. E.g.:
看起来它什么都不做——它只是返回它的参数。但是,因为FunAs是一个。net类型,f#将自动编译任何调用站点,它将一个有趣的表达式转换为代码,生成合适的LINQ查询表达式。例如:
let linqExpr = FunAs.LinqExpression(fun (e:MyEntity) -> e.Id = 42)
Here, linqExpr
will be of type Expression>
.
这里,linqExpr将是类型表达式
>。
The key to this is that this method is a member of a .NET Type. If you try the exact same thing with an ordinary F# function:
关键是这个方法是。net类型的成员。如果你用一个普通的f#函数来做同样的事情:
let funAsLinqExpression<'T, 'TResult>(e: Expression>) = e
which seems like it should mean exactly the same thing as FunAs.LinqExpression
, you'll find that you can't call it in the same way. E.g., if you try this:
这看起来应该和FunAs完全一样。LinqExpression,你会发现你不能用同样的方法调用它。如果你尝试一下:
let linqExpr = funAsLinqExpression(fun (e:MyEntity) -> e.Id = 42)
You'll get a (slightly unhelpful) error: 'This function takes too many arguments, or is used in a context where a function is not expected`.
您将会得到一个(稍微没有帮助的)错误:“这个函数使用了太多的参数,或者是在不需要函数的情况下使用”。
By making this function a member of a .NET type, we can take advantage of F#'s helpful "You seem to be invoking a .NET API that expects a LINQ-style expression, let me take care of that for you" feature.
通过使这个函数成为。net类型的成员,我们可以利用f#的帮助“您似乎正在调用一个期望linq风格表达式的. net API,让我来为您处理”特性。
(It's possible that there's some more explicit way of asking the LINQ compiler to perform this same trick for you without bringing a .NET type into the picture, but I've not found it.)
(可能有一些更明确的方式要求LINQ编译器为您执行相同的技巧,而无需将. net类型引入到图片中,但我没有找到它。)