简体   繁体   English

将F#引用转换为LINQ表达式

[英]Converting F# Quotations into LINQ Expressions

I can convert a quotation of type Expr<'a -> 'b> to a Linq expression via the following snippet: 我可以通过以下代码段将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)

Now I want to convert a quotation of type Expr<'a * 'b -> 'c> or maybe even Expr<'a -> 'b -> 'c> to a Linq Lambda Expression of type Expression<Func<'a,'b'c>> . 现在我想将Expr<'a * 'b -> 'c>或甚至Expr<'a -> 'b -> 'c>类型的引用转换为Expression<Func<'a,'b'c>>类型的Linq Lambda表达式Expression<Func<'a,'b'c>>

How can I do this? 我怎样才能做到这一点?

Regards, forki 此致,forki

I'm not sure if this is directly supported by the LINQ modules available in the F# PowerPack. 我不确定这是否由F#PowerPack中提供的LINQ模块直接支持。 However, you can implement your own post-processing of the LINQ expression produced by F# libraries to turn it into a C# lambda function of the usual form: 但是,您可以实现自己对F#库生成的LINQ表达式的后处理,将其转换为通常形式的C#lambda函数:

The following function takes a LINQ expression which is constructed as multiple nested LambdaExpression expressions of a single parameter (that is, the structure produced by F# translator) and returns a list of parameters and body of the inner-most expression: 以下函数采用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

Now you can use it to get an ordinary Func delegate out of type such as int -> int -> int -> int like this: 现在你可以使用它来获取一个普通的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)

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

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