简体   繁体   English

F#引用对象图

[英]F# quotations object graph

In C# I could create a string representation of an object graph fairly easily with expression trees. 在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");
}

In F# I've been looking at Quotations to attempt to do the same thing, and can't quite figure it out. 在F#中我一直在看引文试图做同样的事情,并且无法弄明白。 I've attempted converting the quotation into an Expression using the PowerPack libraries, but have had no luck so far, and the information on the internet seems fairly sparse on this topic. 我曾尝试使用PowerPack库将引用转换为Expression,但到目前为止还没有运气,而且互联网上的信息在这个主题上看起来相当稀少。

If the input is: 如果输入是:

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

the output should be "myobject.MyProperty" 输出应为“myobject.MyProperty”

You can see what you get from quotation expression in fsi 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, [])

You can find description of all active patterns available to parse qoutations into 您可以找到可用于解析qoutations的所有活动模式的描述

manual\\FSharp.Core\\Microsoft.FSharp.Quotations.Patterns.html 手动\\ FSharp.Core \\ Microsoft.FSharp.Quotations.Patterns.html

under your F# installation directory or at msdn site 在您的F#安装目录下或在msdn站点下

There is nice Chris Smith's book "Programming F#" with chapter named "Quotations" :) 有很好的Chris Smith的书“Programming F#”,章节名为“Quotations”:)

So, after all, just try to write simple parser: 所以,毕竟,只是尝试编写简单的解析器:

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 And of course you will need some code to translate AST to human readable format. PS当然,您需要一些代码才能将AST转换为人类可读的格式。

I'm unsure what the state of things was back when you asked this question, but today you can convert an F# Quotation to an Expression using the PowerPack like so: 当你提出这个问题时,我不确定事情的状态是什么,但今天你可以使用PowerPack将F#Quotation转换成表达式,如下所示:

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

Also, I've been developing a library Unquote which is able to decompile many F# Quotations into F# single-line non-light syntax code. 此外,我一直在开发一个库Unquote ,它能够将许多F#Quotations反编译成F#单行非轻语法代码。 It can easily handle simple instance PropertyGet expressions like your required input / output: 它可以轻松处理简单的实例PropertyGet表达式,如您所需的输入/输出:

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

See my answer to a similar question for more information or just visit Unquote's home page. 有关更多信息,请参阅我对类似问题的回答 ,或者访问Unquote的主页。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM