Tôi đang sử dụng F # 3.0 với .NET 4.5 beta và tôi đang cố chuyển đổi báo giá F # loại Expr<'a -> 'b>
thành LINQ Expression<Func<'a, 'b>>
.Cách chuyển đổi Expr <'a -> 'b> thành Biểu thức <Func <'a, obj>>
Tôi đã tìm thấy một số câu hỏi có giải pháp cho vấn đề này, nhưng những kỹ thuật đó dường như không hoạt động nữa, có lẽ do thay đổi trong F # 3.0 hoặc .NET 4.5.
Trong cả hai trường hợp, khi tôi chạy mã từ các giải pháp của một trong hai câu hỏi, các hành động sau ném một ngoại lệ:
mc.Arguments.[0] :?> LambdaExpression
... nơi mc
là MethodCallExpression
. Ngoại lệ là:
System.InvalidCastException: Không thể truyền đối tượng thuộc loại 'System.Linq.Expressions.MethodCallExpressionN' vào loại 'System.Linq.Expressions.LambdaExpression'.
Không, dấu "N" bổ sung ở cuối MethodCallExpressionN
không phải là lỗi đánh máy. Còn ai có đề nghị nào không? Cảm ơn.
CẬP NHẬT
Đây là một bản tái tạo hoàn chỉnh. Nó chỉ ra mã này hoạt động tốt trên một biểu thức như <@ fun x -> x + 1 @>
. Vấn đề của tôi là trong trường hợp của tôi, tôi cần phải chuyển đổi một số Expr<'a -> 'b>
thành Expr<'a -> obj>
để tôi không phải vứt bỏ tất cả các biểu thức lambda của tôi với box
. Tôi đã làm như vậy bằng cách ghép các biểu thức ban đầu vào một trong những: <@ %exp >> box @>
. Điều này tạo ra một đối tượng với đúng loại, nhưng mã để chuyển đổi thành Expression<Func<'a, obj>>
không còn hoạt động nữ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
Có thể bạn đang bị phạt vì sử dụng phong cách không có điểm. Điều gì sẽ xảy ra nếu bạn sử dụng hộp "<@ fun x ->% exp x |> @>' thay thế? Khi bạn sử dụng kiểu không có điểm, biểu thức bạn đang chuyển đổi không phải là lambda, đó là một ứng dụng. – kvb
@kvb - Đó là một suy nghĩ tốt, nhưng khi tôi sử dụng cấu trúc đó, nó gạch chân '% exp' và nói với tôi" Giá trị này không phải là một hàm và không thể được áp dụng "và từ chối biên dịch. –
Tuy nhiên, '<@ fun x -> x |>% exp |> box @> 'hiện biên dịch. Thật không may, nó nhận được lỗi tương tự khi tôi cố gắng chuyển đổi nó. –