Sto usando F # 3.0 con .NET 4.5 beta, e sto cercando di convertire un F # citazione di tipo Expr<'a -> 'b>
ad un LINQ Expression<Func<'a, 'b>>
.Come convertire Espr <'a -> 'b> per Expression <Func <'a, obj>>
Ho trovato diverse domande che hanno soluzioni a questo problema, ma quelle tecniche non sembrano funzionare più, presumibilmente a causa di modifiche in F # 3.0 o .NET 4.5.
In entrambi i casi, quando si esegue il codice dalle soluzioni di due domande, l'azione seguente genera un'eccezione:
mc.Arguments.[0] :?> LambdaExpression
... dove mc
è un MethodCallExpression
. L'eccezione è:
System.InvalidCastException: Impossibile eseguire il cast oggetto di tipo 'System.Linq.Expressions.MethodCallExpressionN' digitare 'System.Linq.Expressions.LambdaExpression'.
No, la "N" in più alla fine di MethodCallExpressionN
non è un errore di battitura. Qualcuno ha un suggerimento? Grazie.
UPDATE
Ecco una riproduzione completa. Risulta che questo codice funziona bene su un'espressione come <@ fun x -> x + 1 @>
. Il mio problema è che nel mio caso ho bisogno di convertire un Expr<'a -> 'b>
in Expr<'a -> obj>
in modo che non debba sporcare tutte le mie espressioni lambda con box
. L'ho fatto collegando l'espressione originale a questo: <@ %exp >> box @>
. Questo produce un oggetto con il tipo corretto, ma il codice da convertire in Expression<Func<'a, obj>>
non funziona più.
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
Forse sei stato punito per il tuo uso di stile point-free. Cosa succede se usi '<@ fun x ->% exp x |> box @>'? Quando usi lo stile point-free, l'espressione che stai convertendo non è una lambda, è un'applicazione. – kvb
@kvb - Questa è una buona idea, ma quando uso quel costrutto, sottolinea '% exp' e mi dice" Questo valore non è una funzione e non può essere applicato "e si rifiuta di compilare. –
Tuttavia, '<@ fun x -> x |>% exp |> box @>' compila. Sfortunatamente ottiene lo stesso errore quando provo a convertirlo. –