我可以在StructuredFormatDisplayAttribute中使用多个属性吗?

Sve*_*sen 4 f# string-formatting f#-interactive

我正在玩StructuredFormatDisplay,我假设我可以使用多个属性Value,但似乎并非如此.这个问题(和接受的答案)一般都谈到定制,但给出的例子只使用一个属性.在使用此属性时,MSDN没有帮助.

这是我的例子:

[<StructuredFormatDisplay("My name is {First} {Last}")>]
type Person = {First:string; Last:string}
Run Code Online (Sandbox Code Playgroud)

如果我然后尝试这个:

let johnDoe = {First="John"; Last="Doe"}
Run Code Online (Sandbox Code Playgroud)

我最终得到了这个错误:

<StructuredFormatDisplay exception: Method 'FSI_0038+Person.First} {Last' not found.>

这个错误似乎暗示它只捕获了我提到的第一个属性,Value但我很难说有信心.

我已经发现我可以通过声明我的类型来解决这个问题:

[<StructuredFormatDisplay("My name is {Combined}")>]
type Person = {First:string; Last:string} with
    member this.Combined = this.First + " " + this.Last
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有人可以解释为什么我不能使用多个属性,或者如果可以的话,我缺少什么语法.

我在源头做了一些挖掘并发现了这个评论:

在此版本的F#中,唯一有效值的格式为PreText {PropertyName} PostText

但是我无法找到实际实现该限制的地方,所以也许更熟悉代码库的人可以简单地指出我实施这个限制的地方并且我承认失败.

Tom*_*cek 5

来自F#存储库的相关代码位于第868行的sformat.fs文件中.省略了大量细节和一些错误处理,它看起来像这样:

let p1 = txt.IndexOf ("{", StringComparison.Ordinal) 
  let p2 = txt.LastIndexOf ("}", StringComparison.Ordinal) 
  if p1 < 0 || p2 < 0 || p1+1 >= p2 then  
      None  
  else 
    let preText = if p1 <= 0 then "" else txt.[0..p1-1] 
    let postText = if p2+1 >= txt.Length then "" else txt.[p2+1..] 
    let prop = txt.[p1+1..p2-1] 
    match catchExn (fun () -> getProperty x prop) with 
    | Choice2Of2 e -> 
        Some (wordL ("<StructuredFormatDisplay exception: " + e.Message + ">")) 
    | Choice1Of2 alternativeObj -> 
        let alternativeObjL =  
          match alternativeObj with  
          | :? string as s -> sepL s 
          | _ -> sameObjL (depthLim-1) Precedence.BracketIfTuple alternativeObj 
        countNodes 0 // 0 means we do not count the preText and postText  
        Some (leftL preText ^^ alternativeObjL ^^ rightL postText) 
Run Code Online (Sandbox Code Playgroud)

因此,您可以很容易地看到它查找第一个{和最后一个},然后在它们之间选择文本.因此foo {A} {B} bar,它提取文本A} {B.

这听起来像是一个愚蠢的限制,也是一个难以改善的.所以,随意在F#GitHub页面上打开一个问题并考虑发送拉取请求!