Jak przekonwertować Expr <'a ->' b> na Expression <Func <'a, obj >>
Używam F # 3.0 z beta .NET 4.5 i próbuję przekonwertować cytat typu F #Expr<'a -> 'b>
do LINQExpression<Func<'a, 'b>>
.
Znalazłem kilka pytań, które mają rozwiązanie tego problemu, ale techniki te nie wydają się już działać, prawdopodobnie z powodu zmian w F # 3.0 lub .NET 4.5.
Konwersja notowań F # na wyrażenia LINQExpression<Func<T, bool>>
z F # funcW obu przypadkach, gdy uruchamiam kod z rozwiązań któregokolwiek z pytań, następująca akcja zgłasza wyjątek:
mc.Arguments.[0] :?> LambdaExpression
...gdziemc
jestMethodCallExpression
. Wyjątkiem jest:
System.InvalidCastException: Nie można rzutować obiektu typu „System.Linq.Expressions.MethodCallExpressionN” na „System.Linq.Expressions.LambdaExpression”.
Nie, dodatkowe „N” na końcuMethodCallExpressionN
nie jest literówką. Ktokolwiek ma jakieś sugestie? Dzięki.
AKTUALIZACJA
Oto pełna reprodukcja. Okazuje się, że ten kod działa poprawnie w wyrażeniu takim jak<@ fun x -> x + 1 @>
. Moim problemem jest to, że w moim przypadku muszę przekonwertowaćExpr<'a -> 'b>
wExpr<'a -> obj>
tak, że nie muszę zaśmiecać wszystkich moich wyrażeń lambdabox
. Zrobiłem to, łącząc oryginalne wyrażenie z tym:<@ %exp >> box @>
. Daje to obiekt o prawidłowym typie, ale kod do konwersjiExpression<Func<'a, obj>>
nie działa.
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