我继续为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")
Run Code Online (Sandbox Code Playgroud)
如何重写这个匹配才能返回("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);
Run Code Online (Sandbox Code Playgroud)
您可以使用 F# powerpack 来实现此目的:
open Microsoft.FSharp.Metadata
...
| Call(_, mi, _) ->
let ty = Microsoft.FSharp.Metadata.FSharpEntity.FromType(mi.DeclaringType)
let name = ty.DisplayName // name is List
Run Code Online (Sandbox Code Playgroud)
但是,我不认为是否可以使用 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
Run Code Online (Sandbox Code Playgroud)