2009-12-18 8 views
5

En C#, je pouvais créer assez facilement une représentation sous forme de chaîne d'un graphe d'objet avec des arbres d'expression.F # citations graphique de l'objet

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

En F # J'ai regardé Citations pour tenter de faire la même chose, et ne peut pas comprendre tout à fait dehors. J'ai essayé de convertir la citation en Expression en utilisant les bibliothèques PowerPack, mais je n'ai pas eu de chance jusqu'à maintenant, et les informations sur Internet semblent assez rares sur ce sujet.

Si l'entrée est:

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

la sortie doit être "myobject.MyProperty"

+1

Dunno la réponse (les citations ne sont pas mon fort), mais je veux m'assurer que vous avez lu http://blogs.msdn.com/dsyme/archive/2009/10/23/a-quick-refresh-on- query-support-in-the-f-power-pack.aspx qui sont les meilleurs docs actuels sur le support Quotation-> Expression dans le PowerPack. – Brian

Répondre

5

Vous pouvez voir ce que vous obtenez de l'expression de citation en session 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, []) 

Vous peut trouver la description de tous les modèles actifs disponibles pour analyser les qoutations en

manuel \ FSharp.Core \ Microsoft.FSharp.Quotations.Patterns.html

sous votre répertoire d'installation F # ou à msdn site

Il est beau livre de Chris Smith "Programmation F #" avec le chapitre nommé "Citations" :)

Alors, après tout, juste essayer d'écrire analyseur simple:

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 Et bien sûr, vous aurez besoin de code pour traduire AST en format lisible par l'homme.

+0

fyi - ces exemples de code obsolètes ne seront pas compilés sur F # 2.0+ (List.fold_left est maintenant List.fold, PropGet est maintenant PropertyGet, et ocaml-style chaîne concat (^) produit des avertissements. –

3

Je ne suis pas sûr ce que l'état des choses était de retour quand vous avez posé cette question, mais aujourd'hui vous pouvez convertir un F # Citation à une expression en utilisant la PowerPack comme ceci:

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

Aussi, j'ai Était en train de développer une bibliothèque Unquote qui est capable de décompiler de nombreuses citations F # en code de syntaxe non-légère à une seule ligne F #. Il peut facilement gérer des expressions simples exemple de PropertyGet comme votre entrée/sortie requise:

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

Voir mon answer à une question similaire pour plus d'informations ou visiter la page d'accueil de Unquote.