可以将StructuredFormatDisplayAttribute用作扩展方法的一部分

时间:2012-10-02 13:10:59

标签: f# formatting type-extension

我不认为它可能,但你可以做类似的事情,以允许通过类型扩展名进行自定义格式化吗?

[<StructuredFormatDisplayAttribute("Rate: {PrettyPrinter}")>]
type Rate with 
    member x.PrettyPrinter = x.Title + string x.Value

注意:它看起来可以作为内部扩展(相同的程序集),但不能作为可选扩展名

如果不是,我猜这可能是一个功能请求,除非有人有一个不错的选择?

2 个答案:

答案 0 :(得分:2)

不,这是不可能的。在FSI中,您可以使用fsi.AddPrinter来自定义输出。

fsi.AddPrinter (fun (x: Rate) -> x.Title + string x.Value)

修改

对于常规字符串格式,您可以将Printf%a格式说明符一起使用。一些额外的功能可以使这更方便。

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module Rate =
  let stringify (x: Rate) = x.Title + string x.Value
  let print rate = printf "%s" (stringify rate)

printf "Rate: %a" (fun _ -> Rate.print) rate
let formattedString = sprintf "Rate: %a" (fun _ -> Rate.stringify) rate

答案 1 :(得分:2)

正如您所说,StructuredFormatDisplayAttribute仅适用于编译为属性的成员(包括标准属性,相同的程序集扩展,但不包括扩展成员)。在封面下,使用反射访问它(如你所见,它也可以是私有的):

let getProperty (obj: obj) name =
    let ty = obj.GetType()
    ty.InvokeMember(name, (BindingFlags.GetProperty ||| BindingFlags.Instance ||| 
        BindingFlags.Public ||| BindingFlags.NonPublic), 
        null, obj, [| |],CultureInfo.InvariantCulture)

如果您需要这个用于调试目的,那么DebuggerTypeProxy属性可能是另一种选择(请参阅MSDN documentation)。这允许您使用用于在调试器中显示类型的代理类型替换原始类型。 (但我认为该属性仍然必须放在实际的类型定义上,而不是放在扩展名上。)