Как конвертировать Expr <'a ->' b> в выражение <Func <'a, obj >>
Я использую F # 3.0 с бета-версией .NET 4.5, и я пытаюсь преобразовать цитату типа F # типаExpr<'a -> 'b>
на LINQExpression<Func<'a, 'b>>
.
Я нашел несколько вопросов, которые имеют решение этой проблемы, но эти методы, похоже, больше не работают, возможно, из-за изменений в F # 3.0 или .NET 4.5.
Converting F# Quotations into LINQ ExpressionsExpression<Func<T, bool>>
from a F# func
В обоих случаях, когда я запускаю код из решений любого вопроса, следующее действие выдает исключение:
mc.Arguments.[0] :?> LambdaExpression
...гдеmc
этоMethodCallExpression
, Исключением является:
System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.MethodCallExpressionN' to type 'System.Linq.Expressions.LambdaExpression'.
Нет, дополнительный "N" в концеMethodCallExpressionN
это не опечатка. У кого-нибудь есть предложение? Благодарю.
UPDATE
Вот полное воспроизведение. Оказывается, этот код прекрасно работает с такими выражениями, как<@ fun x -> x + 1 @>
, Моя проблема в том, что в моем случае мне нужно преобразоватьExpr<'a -> 'b>
вExpr<'a -> obj>
чтобы мне не приходилось засорять все лямбда-выраженияbox
, Я сделал это, объединив оригинальное выражение с этим:<@ %exp >> box @>
, Это создает объект с правильным типом, но код для преобразования вExpression<Func<'a, obj>>
больше не работает.
module Expr =
open System
open System.Linq.Expressions
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation
let rec private 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
let ToFuncExpression (expr:Expr<'a -> 'b>) =
let args, body = expr.ToLinqExpression() |> translateExpr
Expression.Lambda<Func<'a, 'b>>(body, Array.ofList args)
let exp = <@ fun x -> x + 1 @>
let r = Expr.ToFuncExpression <@ %exp >> box @>
printfn "%A" r