Can StructuredFormatDisplayAttribute be used as part of an extension method

356 Views Asked by At

I dont think its possible but can you do something similar to this to allow custom formatting via a Type extension?

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

Note: It looks to be possible as an intrinsic extension(Same assembly) but not as an optional extension.

If not I guess this could be a feature request, unless anyone has a nice alternative?

2

There are 2 best solutions below

4
Daniel On

No, it's not possible. In FSI, you can use fsi.AddPrinter to customize output.

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

EDIT

For general string formatting, you can use Printf with the %a format specifier. A few extra functions can make this more convenient.

[<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
Tomas Petricek On

As you say, there StructuredFormatDisplayAttribute works only for members that are compiled as properties (that includes standard properties, same assembly extensions, but not extension members). Under the cover, it is accessed using reflection (as you see, it can be private too):

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

If you need this for debugging purposes, then the DebuggerTypeProxy attribute might be an alternative (see MSDN documentation). This allows you to replace the original type with a proxy type that is used for showing the type in a debugger. (But I think the attribute still has to be placed on the actual type definition and not on an extension.)

Related Questions in F#