2009-12-18 22 views
5

C# İçindekiler ağaçlarıyla bir nesne grafiğinin dize olarak temsilini kolayca oluşturabilirim.F # alıntıları nesne grafiği

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"); 
} 

F # Aynı şeyleri yapmaya çalışmak için Tekliflere bakıyordum ve tam olarak anlayamıyorum. PowerPack kütüphanelerini kullanarak teklifin bir İfadeye dönüştürülmesini denedim, ancak şimdiye kadar hiç şansım olmadı ve internetteki bilgiler bu konuda oldukça seyrek görünüyor. giriş

ise:

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

çıktı "myObject.myProperty" olmalıdır

+1

Yanıtın cevabı (alıntılar benim forte'm değil), ancak http://blogs.msdn.com/dsyme/archive/2009/10/23/a-quick-refresh-on- sayfasını okuduğunuzdan emin olmak istersiniz. PowerPack'deki Quotation-> Expression desteği hakkında en iyi güncel dokümanlar olan sorgu-destek-in-the-f-power-pack.aspx. – Brian

cevap

5

Sen fsi oturumda tırnak ifadeden ne olsun görebilirsiniz:

> 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, []) 

You adresinden ayrıştırmak için kullanılabilir olan tüm etkin modellerin açıklamasını bulabilirsinizkılavuzu \ FSharp.Core \ Microsoft.FSharp.Quotations.Patterns.html sizin F # yükleme dizininde altında veya msdn site

de

"Alıntılar" adlı bölümde güzel Chris Smith'in kitabı "Programlama F #" Orada :)

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:

Yani, sonuçta, sadece basit ayrıştırıcı yazmaya çalışıyorum Ve tabii ki AST'yi insan okunabilir formatına çevirmek için bazı kodlara ihtiyacınız olacak.

+0

fyi - bu kod örnekleri güncel değil F # 2.0 + (List.fold_left şimdi List.fold, PropGet şimdi PropertyGet ve ocaml tarzı dize concat (^) uyarılar üretir derlenmez. –

3

Sana bu soru sorulduğunda şeylerin devlet geri ne emin değilim ama bugün şöyle PowerPack'i kullanarak bir İfade ile bir F # Fiyatlandırmamızı dönüştürebilirsiniz: Ben de

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

ettik Pek çok F # Teklifini F # tek satırlı ışık olmayan sözdizim koduna dönüştürebilen bir kitaplık Unquote geliştirmekteyim. Kolayca gerekli giriş/çıkış gibi basit örneği PropertyGet ifadeler işleyebilir:

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

fazla bilgi için benim answer benzer soruya bakın ya da sadece unquote ana sayfasını ziyaret edin.