我可以通过以下代码段将Expr<'a -> 'b>
类型的引号转换为Linq表达式:
/// Converts a F# Expression to a LINQ Lambda
let toLambda (exp:Expr) =
let linq = exp.ToLinqExpression() :?> MethodCallExpression
linq.Arguments.[0] :?> LambdaExpression
/// Converts a Lambda quotation into a Linq Lamba Expression with 1 parameter
let ToLinq (exp : Expr<'a -> 'b>) =
let lambda = toLambda exp
Expression.Lambda<Func<'a, 'b>>(lambda.Body, lambda.Parameters)
现在,我想将类型为Expr<'a * 'b -> 'c>
或甚至Expr<'a -> 'b -> 'c>
的引号转换为Expression<Func<'a,'b'c>>
类型的Linq Lambda表达式。
我该怎么做?
此致 forki
答案 0 :(得分:13)
我不确定F#PowerPack中可用的LINQ模块是否直接支持它。但是,您可以实现自己对F#库生成的LINQ表达式的后处理,将其转换为通常形式的C#lambda函数:
以下函数采用LINQ表达式,该表达式构造为单个参数的多个嵌套LambdaExpression
表达式(即F#转换器生成的结构),并返回最内层的参数列表和主体表达式:
let rec translateExpr (linq:Expression) =
match linq with
| :? MethodCallExpression as mc ->
let le = mc.Arguments.[0] :?> LambdaExpression
let args, body = translateExpr le.Body
le.Parameters.[0] :: args, body
| _ -> [], linq
现在,您可以使用它来获取普通的Func
委托类型,例如int -> int -> int -> int
,如下所示:
let linq = (<@@ fun a b c -> (a + b) * c @@>).ToLinqExpression()
let args, body = translateExpr liq
let f = Expression.Lambda<Func<int, int, int, int>>
(body, args |> Array.ofSeq)
f.Compile().Invoke(10, 11, 2)