我正在使用带有 .NET 4.5 beta 的 F# 3.0,并且我正在尝试将 F# 引用类型Expr<'a -> 'b>转换为 LINQ Expression<Func<'a, 'b>>。
我发现了几个可以解决这个问题的问题,但这些技术似乎不再起作用,可能是由于 F# 3.0 或 .NET 4.5 的变化。
在这两种情况下,当我从任一问题的解决方案中运行代码时,以下操作都会引发异常:
mc.Arguments.[0] :?> LambdaExpression
...在mc哪里MethodCallExpression. 例外是:
System.InvalidCastException:无法将“System.Linq.Expressions.MethodCallExpressionN”类型的对象转换为“System.Linq.Expressions.LambdaExpression”类型。
不,末尾多余的“N”MethodCallExpressionN不是错字。有人有建议吗?谢谢。
更新
这是一个完整的复制品。事实证明,这段代码在像<@ fun x -> x + 1 @>. 我的问题是,在我的情况下,我需要将 an 转换Expr<'a -> 'b>为Expr<'a -> obj>,这样我就不必将所有的 lambda 表达式都用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