Formatters are responsible for representing an object as a string
. Formatters are used in two contexts: logging and caching. This article describes how to implement a custom formatter.
When to implement a custom formatter
You may consider implementing a custom formatter in two situations:
You want the object to be formatted differently in different contexts, i.e. you want the logging representation to be different than the caching representation or than the
ToString
representation.The formatting is performance-critical. Since custom formatters are based on the UnsafeStringBuilder class, they are much faster than formatters based on
ToString
orstring.Format
.
Implementing the IFormattable interface
If you own the source code of a type, the easiest way to implement a custom formatter is to make the type implement the IFormattable interface, which has a single method named Format(UnsafeStringBuilder, FormattingRole).
The following example shows how to implement the IFormattable interface:
using PostSharp.Patterns.Diagnostics;
using PostSharp.Patterns.Formatters;
namespace PostSharp.Samples.Logging
{
class CustomerData : PostSharp.Patterns.Formatters.IFormattable
{
public string FirstName { get; set; }
public string LastName { get; set; }
[Log(AttributeExclude=true)]
void Patterns.Formatters.IFormattable.Format(UnsafeStringBuilder stringBuilder, FormattingRole role)
{
stringBuilder.Append("{CustomerData FirstName=\"");
stringBuilder.Append(this.FirstName);
stringBuilder.Append("\", LastName=\"");
stringBuilder.Append(this.LastName);
stringBuilder.Append("}");
}
}
}
Tip
To prevent the formatter from being logged, add [Log(AttributeExclude=true)]
to the formatting method.
When you implement the IFormattable interface, you don't need to register the formatter because the formatter is the object itself.
Implementing the Formatter class
If you don't own the source code of a type, you cannot implement the IFormattable. Instead, you can create a new class derived from the Formatter<T> class and implement the Write(UnsafeStringBuilder, T) method.
The following example illustrates a formatter for the int class.
using PostSharp.Patterns.Diagnostics;
using PostSharp.Patterns.Formatters;
[Log(AttributeExclude=true)]
class FancyIntFormatter : Formatter<int>
{
public override void Write(UnsafeStringBuilder stringBuilder, int value)
{
switch ( value )
{
case 0:
stringBuilder.Append("zero");
break;
case 1:
stringBuilder.Append("one");
break;
case 2:
stringBuilder.Append("two");
break;
case 3:
stringBuilder.Append("three");
break;
default:
stringBuilder.Append(value);
break;
}
}
}
Tip
To prevent the formatter from being logged, add [Log(AttributeExclude=true)]
to the formatting method.
Registering the custom formatter
Creating a new formatter class does not cause PostSharp to use it. You still need to register it.
Use the following code to register your formatter with PostSharp Logging:
LoggingServices.Formatters.Register(new FancyIntFormatter());
To use the same formatter in PostSharp Caching, use:
CachingServices.Formatters.Register(new FancyIntFormatter());
See Also
Other Resources