Преобразование цитат F# в выражения LINQ

Я могу преобразовать цитату типа 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 типа Expression<Func<'a,'b'c>>.

Как я могу сделать это?

С уважением, вилкообразный

9
задан forki23 21 April 2010 в 11:34
поделиться

1 ответ

Я не уверен, поддерживается ли это напрямую модулями LINQ, доступными в F # PowerPack. Однако вы можете реализовать собственную постобработку выражения LINQ, созданного библиотеками F #, чтобы превратить его в лямбда-функцию C # обычной формы:

Следующая функция принимает выражение 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)
13
ответ дан 4 December 2019 в 15:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: