gpt4 book ai didi

linq - 如何将 Expr <'a -> ' b> 转换为 Expression>

转载 作者:行者123 更新时间:2023-12-04 20:17:18 26 4
gpt4 key购买 nike

我正在使用带有 .NET 4.5 beta 的 F# 3.0,并且我正在尝试转换 Expr<'a -> 'b> 类型的 F# 引用到 LINQ Expression<Func<'a, 'b>> .

我发现了几个可以解决这个问题的问题,但这些技术似乎不再起作用,可能是由于 F# 3.0 或 .NET 4.5 的变化。

  • Converting F# Quotations into LINQ Expressions
  • Expression<Func<T, bool>> from a F# func

  • 在这两种情况下,当我从任一问题的解决方案中运行代码时,以下操作都会引发异常:
    mc.Arguments.[0] :?> LambdaExpression

    ...在哪里 mcMethodCallExpression .异常(exception)是:

    System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.MethodCallExpressionN' to type 'System.Linq.Expressions.LambdaExpression'.



    不, MethodCallExpressionN 末尾的额外“N”不是错字。有人有建议吗?谢谢。

    更新

    这是一个完整的复制品。事实证明,这段代码在 <@ fun x -> x + 1 @> 这样的表达式上运行良好.我的问题是,在我的情况下,我需要转换 Expr<'a -> 'b>进入 Expr<'a -> obj>这样我就不必用 box 乱扔我所有的 lambda 表达式了.我通过将原始表达式拼接到这个表达式中来做到这一点: <@ %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

    最佳答案

    您能否发布更完整的示例并包含您尝试转换的 F# 表达式?

    我尝试使用最少的示例测试 .NET 4.5 上的行为,它对我有用。这是我所做的:

  • 我创建了新的 F# 3.0 项目并复制了 Linq.fsLinq.fsi来自 F# PowerPack 2.0 版本。 (或者在 F# 3.0 的某个地方是否有 ToLinqExpression 方法的 3.0 版本?)
  • 我使用了 Daniel's earlier answer 中的代码并按如下方式调用该函数:
    let r = toLinq <@ fun x -> x + 1 @>
    printfn "%A" r

    这没有抛出任何异常,它打印了 x => (x + 1) ,这对我来说是正确的。

  • 编辑:要回答更新后的问题 - 您提到的两个代码示例(我的和 Daniel 的)都假定引用的主体是一个显式构造的函数,因此它们仅适用于特定结构的引用: <@ fun x -> ... @> .

    您可以通过在显式构造的函数中使用拼接来解决此问题。以下对我有用:
    let exp = <@ fun x -> x + 1 @> 
    let r = toLinq <@ fun a -> box ((%exp) a) @>
    printfn "%A" r

    这包含一个 F# 函数的应用,所以生成的 Expression包含对 ToFSharpFunc 的调用(它将委托(delegate)转换为 F# 函数),然后调用 this。如果您想要 Expression,这可能是个问题标准 .NET 工具可以理解(在这种情况下,您必须对 C# 表达式树进行后处理并删除这些结构)。

    关于linq - 如何将 Expr <'a -> ' b> 转换为 Expression<Func<'a, obj>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10647198/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com