I have a logging interface which I extend with some helpful extension methods as to make it possible for me to pass in a format and a list of arguments to avoid having to use string format every time a call the method. (it also help me follow FXCops culture info rules)
So I can call:
logger.Debug("Created {0} with id {1}",typeof(MyObject).Name ,myObject.Id);
Instead of:
logger.Debug(string.Format("Created {0} with id {1}", typeof(MyObject).Name, myObject.Id));
I now found myself in a bit of a tricky situation because it would be immensely helpful to also get some info in the logs about where the logging was written such as the file, method, and line number. This could be achieved with the neat [CallerMemberName]
, [CallerFilePath]
, and [CallerLineNumber]
attribute.
logger.Debug("Created {0} with id {1}", typeof(MyObject).Name, myObject.Id);
would then give me a log entry such as:
"MyObjectProvider.cs, Provide, line:50 | Created MyObject with id 1564"
The issue here is that the method signature would look like this:
public static void Debug(this ILogger logger, string format [CallerMemberName] string callerMemberName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0, params object[] args)
and that is not possible because the [Caller*]
attributes makes the parameters optional and that doesn't work with the args parameter.
I also tried to make multiple implementations with fixed amount of strings as parameters like this:
public static void Debug(this ILogger logger, string format [CallerMemberName] string callerMemberName = "",string arg, string arg2 , ...etc... , [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0)
but then I get compiler errors saying the "The call is ambiguous between the following methods or properties"
I have almost given up on this issue now but I thought to myself, "Maybe SO can find a solution for me". So here it is... Is it possible to use both params object[] args
and [CallerFilePath]
in any way or is there another way to get the intended result?
You can't combine the two in a method signature. What you could do is one or the other and pass in null
to where you need optional parameters, would this work for you?
Foo(s, null);
public void Foo(string s, params string[] sArray)
{
}
Foo(new string[] {""});
private static void Foo(string[] sArray, string s = "")
{
}
OR
Why not use a class which handles your formatting and make that optional?
public class LogArgs
{
private string _formatString;
private string[] _args;
public LogArgs(string formatString, params string[] args)
{
_formatString = formatString;
_args = args;
}
public override string ToString()
{
return string.Format(_formatString, _args);
}
}
public void Foo(string mandatory, LogArgs optionalParam = null)
{
//Do Stuff
}
Foo("", new LogArgs("{0} is formatted", ""));