如何从引用的表达式匹配中获取模块,函数等的F#名称

时间:2011-01-05 12:49:41

标签: f# quotations

我继续在F#引用的表达式上使用打印机,它不一定非常完美,但我想看看有什么可能。用于分解引用表达式的Microsoft.FSharp.Quotations.PatternsMicrosoft.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")?有可能吗?

仅供参考,这是Stringer Bell和pblasucci帮助的最终解决方案:

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 个答案:

答案 0 :(得分:4)

您可以将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检索功能名称。

修改

正如pblasucci所暗示,您可以使用CompilationSourceName属性来检索源名称:

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