2009-12-18 6 views
5

Trong C# tôi có thể tạo ra một chuỗi đại diện của một đồ thị đối tượng khá dễ dàng với cây biểu thức.F # trích dẫn đồ thị đối tượng

public static string GetGraph<TModel, T>(TModel model, Expression<Func<TModel, T>> action) where TModel : class 
{ 
      var method = action.Body as MethodCallExpression; 
      var body = method != null ? method.Object != null ? method.Object as MemberExpression : method.Arguments.Any() ? method.Arguments.First() as MemberExpression : null : action.Body as MemberExpression; 
      if (body != null) 
      { 
       string graph = GetObjectGraph(body, typeof(TModel)) 
       return graph; 
      } 
      throw new Exception("Could not create object graph"); 
} 

Trong F # Tôi đã xem Báo giá cố gắng làm điều tương tự và không thể đoán được. Tôi đã cố gắng chuyển đổi các báo giá thành một biểu thức bằng cách sử dụng các thư viện PowerPack, nhưng đã không có may mắn cho đến nay, và các thông tin trên internet có vẻ khá thưa thớt về chủ đề này.

Nếu đầu vào là:

let result = getGraph myObject <@ myObject.MyProperty @> 

sản lượng nên được "myobject.MyProperty"

+1

Dunno câu trả lời (trích dẫn không phải là sở trường của tôi), nhưng muốn đảm bảo bạn đã đọc http://blogs.msdn.com/dsyme/archive/2009/10/23/a-quick-refresh-on- query-support-in-the-f-power-pack.aspx là các tài liệu hiện hành tốt nhất về sự hỗ trợ biểu thức-> Expression trong PowerPack. – Brian

Trả lời

5

Bạn có thể xem những gì bạn nhận được từ biểu ngoặc kép trong phiên FSI:

> let v = "abc" 
> <@ v.Length @>;; 
val it : Expr<int> 
= PropGet (Some (PropGet (None, System.String v, [])), Int32 Length, []) 

> <@ "abc".Length @>;; 
val it : Expr<int> 
= PropGet (Some (Value ("abc")), Int32 Length, []) 

Bạn có thể tìm thấy mô tả của tất cả các mẫu đang hoạt động có sẵn để phân tích cú pháp qoutations thành

thủ \ FSharp.Core \ Microsoft.FSharp.Quotations.Patterns.html

dưới F # thư mục cài đặt của bạn hoặc ít msdn site

Có đẹp cuốn sách Chris Smith "Lập trình F #" với chương có tên là "Báo giá" :)

Vì vậy, sau khi tất cả, chỉ cần cố gắng viết phân tích cú pháp đơn giản:

open Microsoft.FSharp.Quotations 
open Microsoft.FSharp.Quotations.Patterns 
open Microsoft.FSharp.Quotations.DerivedPatterns 

let rec getGraph (expr: Expr) = 
    let parse args = 
    List.fold_left (fun acc v -> acc^(if acc.Length > 0 then "," else "")^getGraph v) "" args 
    let descr s = function 
    | Some v -> "(* instance "^s^"*) "^getGraph v 
    | _ -> "(* static "^s^"*)" 
    match expr with 
    | Int32 i -> string i 
    | String s -> sprintf "\"%s\"" s 
    | Value (o,t) -> sprintf "%A" o 
    | Call (e, methodInfo, av) -> 
    sprintf "%s.%s(%s)" (descr "method" e) methodInfo.Name (parse av) 
    | PropGet(e, methodInfo, av) -> 
    sprintf "%s.%s(%s)" (descr "property" e) methodInfo.Name (parse av) 
    | _ -> failwithf "I'm don't understand such expression's form yet: %A" expr 

PS Và tất nhiên bạn sẽ cần một số mã để dịch AST sang định dạng có thể đọc được của con người.

+0

fyi - các ví dụ mã này đã lỗi thời sẽ không biên dịch với F # 2.0+ (List.fold_left bây giờ là List.fold, PropGet bây giờ là PropertyGet và chuỗi ký tự kiểu chuỗi ocaml (^) tạo ra cảnh báo. –

3

tôi không chắc chắn những gì tình trạng thứ đã trở lại khi bạn hỏi câu hỏi này, nhưng hôm nay bạn có thể chuyển đổi một F # Báo giá một biểu thức bằng cách sử dụng PowerPack như vậy:

<@ "asdf".Length @>.ToLinqExpression() 

Ngoài ra, tôi đã đã phát triển một thư viện Unquote có thể dịch ngược nhiều F # Trích dẫn thành mã cú pháp không phải dòng đơn F #. Nó có thể dễ dàng xử lý các biểu dụ PropertyGet đơn giản như đầu vào/đầu ra yêu cầu của bạn:

> decompile <@ "asdf".Length @>;; 
val it : string = ""asdf".Length" 

Xem answer cho một câu hỏi tương tự như của tôi để biết thêm thông tin hoặc chỉ cần truy cập trang chủ của unquote.