一种方法是采取的事实,即调用上期待Expression<Func<...>>
.NET类型方法时,F#会自动执行这种转换。
我不完全确定何时将其添加到语言中,但肯定使用F#4,您不需要将F#表达式显式转换为LINQ。如果你想这样做摆在首位的原因是能够使用LINQ IQueryable
的API(或其他基于表达式的.NET的API),那么它现在只是没有努力的工作,如:
someEfDataContext.MyEntities.Single(fun e -> e.Id = 42)
刚作品。尽管这看起来像一个普通的lambda(我们还没有使用F#的表达式语法),但是它编译为生成F#表达式对象的代码,然后将其传递给LeafExpressionConverter.QuotationToExpression
以将它转换为LINQ表达式对象。
但有时您会想直接在F#中获得LINQ样式表达式对象。 (例如,有时它是有用的编写产生,你会在多个查询使用表达式的F#功能。)在这种情况下,你可以写这样的帮手:
type FunAs() =
static member LinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e
这看起来像它什么也不做 - 它只是返回它的参数。但是,因为FunAs
是一个.NET类型,所以F#会自动编译任何呼叫站点,该站点将fun
表达式调用到生成合适的LINQ查询表达式的代码中。例如: -
let linqExpr = FunAs.LinqExpression(fun (e:MyEntity) -> e.Id = 42)
这里,linqExpr
将Expression<Func<MyEntity, bool>>
类型。
关键是这个方法是一个.NET类型的成员。如果您尝试同样的事情用一个普通的F#功能:
let funAsLinqExpression<'T, 'TResult>(e: Expression<Func<'T, 'TResult>>) = e
这似乎像它应该是说完全一样的东西FunAs.LinqExpression
,你会发现,你不能把它以同样的方式。例如,如果你试试这个:
let linqExpr = funAsLinqExpression(fun (e:MyEntity) -> e.Id = 42)
你会得到一个(略无益的)错误:“这个函数的参数太多,或者在上下文中,其中一个功能不expected`使用。
通过使这个函数成为.NET类型的成员,我们可以利用F#的有用的“你似乎在调用一个需要LINQ风格表达式的.NET API,让我为你处理这个问题”特征。
(这有可能是有要求的LINQ编译器不把.NET类型到图片为您执行这个同样的伎俩,一些更明确的方式,但我还没有发现它。)
哎,没你找到一个更简单的方法来做到这一点? – nicolas 2012-05-01 13:06:16
在旁注中,这里有一个相关的问题,(虽然没有引用,虽然)http://stackoverflow.com/questions/3392000/interop-between-f-and-c-sharp-lambdas – nicolas 2012-05-01 13:08:17