5

在 C# 中,我可以使用表达式树相当容易地创建对象图的字符串表示。

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# 中,我一直在查看引文以尝试做同样的事情,但无法完全弄清楚。我尝试使用 PowerPack 库将引用转换为表达式,但到目前为止没有运气,并且互联网上关于这个主题的信息似乎相当稀疏​​。

如果输入是:

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

输出应该是“myobject.MyProperty”

4

2 回答 2

5

您可以在 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, [])

您可以找到可用于将 qoutations 解析为的所有活动模式的描述

手册\FSharp.Core\Microsoft.FSharp.Quotations.Patterns.html

在您的 F# 安装目录或msdn 站点下

有很好的 Chris Smith 的书“Programming F#”,其中的章节名为“Quotations”:)

所以,毕竟,只需尝试编写简单的解析器:

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 当然,您需要一些代码来将 AST 转换为人类可读的格式。

于 2009-12-19T10:01:39.670 回答
4

当你问这个问题时,我不确定事情的状态是什么,但今天你可以使用 PowerPack 将 F# 引用转换为表达式,如下所示:

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

此外,我一直在开发一个库Unquote,它能够将许多 F# 引号反编译成 F# 单行非轻量级语法代码。它可以轻松处理简单的实例 PropertyGet 表达式,例如您所需的输入/输出:

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

有关更多信息,请参阅我对类似问题的回答或访问 Unquote 的主页。

于 2011-02-27T23:31:45.953 回答