Deferred trace message formatting via Func<string>?
In an application which is compiled with trace enabled, the trace statements will always be executed even if the listener is configured to discard them. Sometimes there is a non-trivial amount of work required to format the trace message, for example:
Trace.Write(IAmExpensiveToRender.ToString() + " requested the following " + string.Join(",", itemList)));
It would be nice to defer the formatting until after the trace messages have been filtered, and one way to implement that would be to to pass in to the trace method a Func<string>
instead of a string
:
Trace.Write((Func<string>)(() => IAmExpensiveToRender.ToString() + " requested the following " + string.Join(",", itemList)));
This is supported by the System.Diagnostics.Trace
class (since it has a catch-all overload which accepts objects) but would require cu开发者_如何学Gostom listeners to call get the actual string by invoking the Func.
I can't imagine that no-one has tried this yet. Are there any existing trace libraries and/or listeners which leverage this? (I couldn't find a single one)
[Update] After a bit of reflectoring, it appears that the Trace overloads which accept a formatting string + params list of arguments already support deferred formatting. They pass the string + args on to the TraceListener which then does the formatting only if the message will actually be written to file.
I don't know about existing trace formatters that supports this.
But since we know that the object
overload for Trace.Write will print the value of .ToString()
; we can take advantage of this:
class DeferredTraceExecutor
{
private readonly Func<string> traceMessage;
public DeferredTraceExecutor(Func<string> traceMessage)
{
this.traceMessage = traceMessage;
}
public override string ToString()
{
return traceMessage();
}
}
Then use in your trace messages as:
Trace.Write(new DeferredTraceExecutor(() => IAmExpensiveToRender.Tostring());
精彩评论