I'm using F# 3.0 with .NET 4.5 beta, and I'm trying to convert an F# quotation of type Expr<'a -> 'b>
to a LINQ Expression<Func<'a, 'b>>
.
I've found several questions that have solutions to this problem, but those techniques don't seem to work any longer, presumably due to changes in either F# 3.0 or .NET 4.5.
In both cases, when I run the code from the solutions of either question, the following action throws an exception:
mc.Arguments.[0] :?> LambdaExpression
...where mc
is a MethodCallExpression
. The exception is:
System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.MethodCallExpressionN' to type 'System.Linq.Expressions.LambdaExpression'.
No, the extra "N" at the end of MethodCallExpressionN
is not a typo. Does anyone have a suggestion? Thanks.
UPDATE
Here's a complete reproduction. It turns out this code works fine on an expression like <@ fun x -> x + 1 @>
. My problem is that in my case I need to convert an Expr<'a -> 'b>
into Expr<'a -> obj>
so that I don't have to litter all my lambda expressions with box
. I did so by splicing the original expression into this one: <@ %exp >> box @>
. This produces an object with the correct type, but the code to convert to Expression<Func<'a, obj>>
no longer works.
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