diff --git a/.gitignore b/.gitignore index 0ced0ba..6796e2b 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,9 @@ bld/ # Visual Studo 2015 cache/options directory .vs/ +# JetBrains project files +.idea/ + # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs index 8b50e08..633622f 100644 --- a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs +++ b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs @@ -321,7 +321,16 @@ internal static MethodInfo SelectConfigurationMethod(IEnumerable can return candidateMethods .Where(m => m.Name == name && m.GetParameters().Skip(1).All(p => p.HasDefaultValue || suppliedArgumentValues.Any(s => s.Key == p.Name))) - .OrderByDescending(m => m.GetParameters().Count(p => suppliedArgumentValues.Any(s => s.Key == p.Name))) + .OrderByDescending(m => + { + var matchingArgs = m.GetParameters().Where(p => suppliedArgumentValues.Any(s => s.Key == p.Name)).ToList(); + + // Prefer the configuration method with most number of matching arguments and of those the ones with + // the most string type parameters to predict best match with least type casting + return new Tuple( + matchingArgs.Count, + matchingArgs.Count(p => p.ParameterType == typeof(string))); + }) .FirstOrDefault(); } diff --git a/test/Serilog.Settings.Configuration.Tests/ConfigurationReaderTests.cs b/test/Serilog.Settings.Configuration.Tests/ConfigurationReaderTests.cs index 79df523..701cfee 100644 --- a/test/Serilog.Settings.Configuration.Tests/ConfigurationReaderTests.cs +++ b/test/Serilog.Settings.Configuration.Tests/ConfigurationReaderTests.cs @@ -165,5 +165,20 @@ public void MethodsAreSelectedBasedOnCountOfMatchedArguments() var selected = ConfigurationReader.SelectConfigurationMethod(options, "DummyRollingFile", suppliedArguments); Assert.Equal(typeof(ITextFormatter), selected.GetParameters()[1].ParameterType); } + + [Fact] + public void MethodsAreSelectedBasedOnCountOfMatchedArgumentsAndThenStringType() + { + var options = typeof(DummyLoggerConfigurationWithMultipleMethodsExtensions).GetTypeInfo().DeclaredMethods.ToList(); + Assert.Equal(3, options.Count(mi => mi.Name == "DummyRollingFile")); + var suppliedArguments = new Dictionary() + { + { "pathFormat", new StringArgumentValue(() => "C:\\") }, + { "formatter", new StringArgumentValue(() => "SomeFormatter, SomeAssembly") } + }; + + var selected = ConfigurationReader.SelectConfigurationMethod(options, "DummyRollingFile", suppliedArguments); + Assert.Equal(typeof(string), selected.GetParameters()[2].ParameterType); + } } } diff --git a/test/Serilog.Settings.Configuration.Tests/DummyLoggerConfigurationWithMultipleMethodsExtensions.cs b/test/Serilog.Settings.Configuration.Tests/DummyLoggerConfigurationWithMultipleMethodsExtensions.cs new file mode 100644 index 0000000..b6be570 --- /dev/null +++ b/test/Serilog.Settings.Configuration.Tests/DummyLoggerConfigurationWithMultipleMethodsExtensions.cs @@ -0,0 +1,42 @@ +using System; +using Serilog.Configuration; +using Serilog.Events; +using Serilog.Formatting; + +namespace Serilog.Settings.Configuration.Tests +{ + using System.Collections.Generic; + + static class DummyLoggerConfigurationWithMultipleMethodsExtensions + { + public static LoggerConfiguration DummyRollingFile( + LoggerSinkConfiguration loggerSinkConfiguration, + ITextFormatter formatter, + IEnumerable pathFormat, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + string outputTemplate = null, + IFormatProvider formatProvider = null) + { + return null; + } + + public static LoggerConfiguration DummyRollingFile( + LoggerSinkConfiguration loggerSinkConfiguration, + ITextFormatter formatter, + string pathFormat, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + string outputTemplate = null, + IFormatProvider formatProvider = null) + { + return null; + } + + public static LoggerConfiguration DummyRollingFile( + LoggerSinkConfiguration loggerSinkConfiguration, + string pathFormat, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum) + { + return null; + } + } +}