Good day!
I'm experimenting with some logging features, in particular adding caller information for logging using interpolated strings. This is in Visual Studio 2022 using C# & .NET 6.0.
I'm trying to add the caller information (name, path, and line number) to the method:
public static void Log<T>(this T logLabel, [InterpolatedStringHandlerArgument("logLabel")] TraceLoggerParamsInterpolatedStringHandler handler)
where T : Enum
{
...
}
The dilemma is the caller information needs to occur before the handler for those arguments to be sent to the constructor of the TraceLoggerParamsInterpolatedStringHandler itself. However, because those attributes require those parameters to have default values, that means the handler requires a default value, too.
If I do:
public static void Log<T>(this T logLabel,
[CallerMemberName] string callerName = "",
[CallerFilePath] string callerFilePath = "",
[CallerLineNumber] int callerLineNumber = -1,
[InterpolatedStringHandlerArgument("logLabel", "callerName", "callerFilePath", "callerLineNumber")] TraceLoggerParamsInterpolatedStringHandler handler = default)
where T : Enum
{
...
}
Then the handler is initialized as the default, it doesn't call the specialized constructor that takes the additional parameters. I don't know if this is a code-gen issue in this case for interpolated strings.
Here is the disasm for the call site:
00007FF84DD2B2AF call Method stub for: System.Runtime.CompilerServices.DefaultInterpolatedStringHandler..ctor(Int32, Int32) (07FF84D6AC1B0h)
00007FF84DD2B2B4 mov rdx,260C53C4D68h
00007FF84DD2B2BE mov rdx,qword ptr [rdx]
00007FF84DD2B2C1 lea rcx,[rbp+0A8h]
00007FF84DD2B2C8 call Method stub for: System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendLiteral(System.String) (07FF84D6AC1F8h)
I'm suspecting however I'll just have to move those parameters after and pass them to the handler explicitly to work around this.
If there is a more elegant solution, I'd appreciate the insight!
Thank you,
Brent Scriver
Turns out this is pretty simple: just add the various
[Caller...]
arguments to yourInterpolatedStringHandler
constructor itself. Like this:Then, you don't need the
[InterpolatedStringHandlerArguments]
at all. Your method signature can just be:And you call it as expected:
The compiler, correctly, turns that into this:
And, by the way, this will still work if you actually do have to use [InterpolatedStringHandlerArgument] with extra arguments.