Как получить F # имя модуля, функции и т. Д. Из совпадения выражений в кавычках - PullRequest
5 голосов
/ 05 января 2011

Я продолжаю работать на принтере для выражений в кавычках F #, это не обязательно должно быть идеально, но я хотел бы увидеть, что возможно. Активные шаблоны в Microsoft.FSharp.Quotations.Patterns и Microsoft.FSharp.Quotations.DerivedPatterns, используемые для декомпозиции выражений в кавычках, как правило, будут предоставлять MemberInfo экземпляры, когда это уместно, их можно использовать для получения имени свойства, функции и т. Д. И их типа "объявления", например как модуль или статический класс. Проблема в том, что я знаю, как получить CompiledName из этих экземпляров, но мне нужно имя F #. Например,

> <@ List.mapi (fun i j -> i+j) [1;2;3] @> |> (function Call(_,mi,_) -> mi.DeclaringType.Name, mi.Name);;
val it : string * string = ("ListModule", "MapIndexed")

Как можно переписать это совпадение для возврата ("List", "mapi")? Возможно ли это?

К вашему сведению, вот мое окончательное полированное решение от Стрингера Белла и помощи Пбласуччи:

let moduleSourceName (declaringType:Type) =
    FSharpEntity.FromType(declaringType).DisplayName

let methodSourceName (mi:MemberInfo) =
    mi.GetCustomAttributes(true)
    |> Array.tryPick 
            (function
                | :? CompilationSourceNameAttribute as csna -> Some(csna)
                | _ -> None)
    |> (function | Some(csna) -> csna.SourceName | None -> mi.Name)

//usage:
let sourceNames =
    <@ List.mapi (fun i j -> i+j) [1;2;3] @> 
    |> (function Call(_,mi,_) -> mi.DeclaringType |> moduleSourceName, mi |> methodSourceName);

1 Ответ

4 голосов
/ 05 января 2011

Для этой цели вы можете использовать F # powerpack:

open Microsoft.FSharp.Metadata
...
| Call(_, mi, _) ->
    let ty = Microsoft.FSharp.Metadata.FSharpEntity.FromType(mi.DeclaringType)
    let name = ty.DisplayName // name is List

Однако я не думаю, что можно получить имя функции с помощью powerpack.

Edit:

Как подсказал pblasucci, вы можете использовать атрибут CompilationSourceName для получения имени источника:

let infos = mi.DeclaringType.GetMember(mi.Name)
let att = infos.[0].GetCustomAttributes(true)
let fName =
    (att.[1] :?> CompilationSourceNameAttribute).SourceName // fName is mapi 
...