10

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>的 Linq Lambda 表达式Expression<Func<'a,'b'c>>

我怎样才能做到这一点?

问候,叉子

4

1 回答 1

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)
于 2010-04-21T14:50:45.977 回答