Преобразование цитат 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>>
,
Как я могу это сделать?
С уважением, форки
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)