F # цитаты граф объекта - PullRequest
       11

F # цитаты граф объекта

5 голосов
/ 19 декабря 2009

В 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 # я смотрю на цитаты, чтобы попытаться сделать то же самое, и не могу понять это. Я пытался преобразовать цитату в Expression с использованием библиотек PowerPack, но пока мне не повезло, и информация в Интернете кажется довольно скудной по этой теме.

Если ввод:

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

вывод должен быть "myobject.MyProperty"

Ответы [ 2 ]

5 голосов
/ 19 декабря 2009

Вы можете увидеть, что вы получаете из выражения кавычки в сеансе 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, [])

Вы можете найти описание всех активных шаблонов, доступных для разбора предложений в

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

в вашем каталоге установки F # или на сайте MSDN

Есть замечательная книга Криса Смита "Программирование на F #" с главой "Цитаты":)

Итак, в конце концов, попробуйте написать простой парсер:

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

P.S. И, конечно же, вам понадобится код для перевода AST в читабельный формат.

3 голосов
/ 28 февраля 2011

Я не уверен, каково было положение вещей, когда вы задавали этот вопрос, но сегодня вы можете преобразовать цитату F # в выражение, используя PowerPack, например:

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

Кроме того, я разрабатывал библиотеку Unquote , которая способна декомпилировать многие цитаты F # в однострочный несветлый синтаксический код F #. Он может легко обрабатывать простые выражения экземпляра PropertyGet, такие как требуемый ввод / вывод:

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

См. Мой ответ на аналогичный вопрос для получения дополнительной информации или просто посетите домашнюю страницу Unquote.

...