diff --git a/README.md b/README.md index 8d3e8fd..744aa13 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,9 @@ Root section name can be changed: ``` ```csharp +var options = new ConfigurationReaderOptions { SectionName = "CustomSection" }; var logger = new LoggerConfiguration() - .ReadFrom.Configuration(configuration, sectionName: "CustomSection") + .ReadFrom.Configuration(configuration, options) .CreateLogger(); ``` @@ -106,8 +107,9 @@ In case of [non-standard](#azure-functions-v2-v3) dependency management you can ```csharp var functionDependencyContext = DependencyContext.Load(typeof(Startup).Assembly); +var options = new ConfigurationReaderOptions(functionDependencyContext) { SectionName = "AzureFunctionsJobHost:Serilog" }; var logger = new LoggerConfiguration() - .ReadFrom.Configuration(hostConfig, sectionName: "AzureFunctionsJobHost:Serilog", dependencyContext: functionDependencyContext) + .ReadFrom.Configuration(hostConfig, options) .CreateLogger(); ``` @@ -119,8 +121,9 @@ var configurationAssemblies = new[] typeof(ConsoleLoggerConfigurationExtensions).Assembly, typeof(FileLoggerConfigurationExtensions).Assembly, }; +var options = new ConfigurationReaderOptions(configurationAssemblies); var logger = new LoggerConfiguration() - .ReadFrom.Configuration(configuration, configurationAssemblies) + .ReadFrom.Configuration(configuration, options) .CreateLogger(); ``` @@ -282,6 +285,8 @@ Some Serilog packages require a reference to a logger configuration object. The When the configuration specifies a discrete value for a parameter (such as a string literal), the package will attempt to convert that value to the target method's declared CLR type of the parameter. Additional explicit handling is provided for parsing strings to `Uri`, `TimeSpan`, `enum`, arrays and custom collections. +Since version 4.0.0, conversion will use the invariant culture (`CultureInfo.InvariantCulture`) as long as the `ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions options)` method is used. Obsolete methods use the current culture to preserve backward compatibility. + ### Static member support Static member access can be used for passing to the configuration argument via [special](https://github.com/serilog/serilog-settings-configuration/blob/dev/test/Serilog.Settings.Configuration.Tests/StringArgumentValueTests.cs#L35) syntax: @@ -377,8 +382,9 @@ public class Startup : FunctionsStartup var functionDependencyContext = DependencyContext.Load(typeof(Startup).Assembly); var hostConfig = sp.GetRequiredService(); + var options = new ConfigurationReaderOptions(functionDependencyContext) { SectionName = "AzureFunctionsJobHost:Serilog" }; var logger = new LoggerConfiguration() - .ReadFrom.Configuration(hostConfig, sectionName: "AzureFunctionsJobHost:Serilog", dependencyContext: functionDependencyContext) + .ReadFrom.Configuration(hostConfig, options) .CreateLogger(); return new SerilogLoggerProvider(logger, dispose: true); diff --git a/src/Serilog.Settings.Configuration/ConfigurationLoggerConfigurationExtensions.cs b/src/Serilog.Settings.Configuration/ConfigurationLoggerConfigurationExtensions.cs index 4e24eef..4ddf35d 100644 --- a/src/Serilog.Settings.Configuration/ConfigurationLoggerConfigurationExtensions.cs +++ b/src/Serilog.Settings.Configuration/ConfigurationLoggerConfigurationExtensions.cs @@ -1,4 +1,4 @@ -// Copyright 2013-2016 Serilog Contributors +// Copyright 2013-2016 Serilog Contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ public static class ConfigurationLoggerConfigurationExtensions /// The dependency context from which sink/enricher packages can be located. If not supplied, the platform /// default will be used. /// An object allowing configuration to continue. + [Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")] public static LoggerConfiguration Configuration( this LoggerSettingsConfiguration settingConfiguration, IConfiguration configuration, @@ -52,15 +53,8 @@ public static LoggerConfiguration Configuration( if (configuration == null) throw new ArgumentNullException(nameof(configuration)); if (sectionName == null) throw new ArgumentNullException(nameof(sectionName)); - var assemblyFinder = dependencyContext == null - ? AssemblyFinder.Auto() - : AssemblyFinder.ForDependencyContext(dependencyContext); - - return settingConfiguration.Settings( - new ConfigurationReader( - configuration.GetSection(sectionName), - assemblyFinder, - configuration)); + var readerOptions = new ConfigurationReaderOptions(dependencyContext) { SectionName = sectionName, FormatProvider = null }; + return Configuration(settingConfiguration, configuration, readerOptions); } /// @@ -73,10 +67,11 @@ public static LoggerConfiguration Configuration( /// The dependency context from which sink/enricher packages can be located. If not supplied, the platform /// default will be used. /// An object allowing configuration to continue. + [Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")] public static LoggerConfiguration Configuration( this LoggerSettingsConfiguration settingConfiguration, IConfiguration configuration, - DependencyContext dependencyContext = null) + DependencyContext dependencyContext) => Configuration(settingConfiguration, configuration, DefaultSectionName, dependencyContext); /// @@ -105,7 +100,8 @@ public static LoggerConfiguration ConfigurationSection( new ConfigurationReader( configSection, assemblyFinder, - configuration: null)); + configuration: null, + formatProvider: null)); } /// @@ -118,6 +114,7 @@ public static LoggerConfiguration ConfigurationSection( /// A section name for section which contains a Serilog section. /// Defines how the package identifies assemblies to scan for sinks and other types. /// An object allowing configuration to continue. + [Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")] public static LoggerConfiguration Configuration( this LoggerSettingsConfiguration settingConfiguration, IConfiguration configuration, @@ -128,9 +125,8 @@ public static LoggerConfiguration Configuration( if (configuration == null) throw new ArgumentNullException(nameof(configuration)); if (sectionName == null) throw new ArgumentNullException(nameof(sectionName)); - var assemblyFinder = AssemblyFinder.ForSource(configurationAssemblySource); - - return settingConfiguration.Settings(new ConfigurationReader(configuration.GetSection(sectionName), assemblyFinder, configuration)); + var readerOptions = new ConfigurationReaderOptions(configurationAssemblySource) { SectionName = sectionName, FormatProvider = null }; + return Configuration(settingConfiguration, configuration, readerOptions); } /// @@ -142,6 +138,7 @@ public static LoggerConfiguration Configuration( /// A configuration object which contains a Serilog section. /// Defines how the package identifies assemblies to scan for sinks and other types. /// An object allowing configuration to continue. + [Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")] public static LoggerConfiguration Configuration( this LoggerSettingsConfiguration settingConfiguration, IConfiguration configuration, @@ -167,7 +164,7 @@ public static LoggerConfiguration ConfigurationSection( var assemblyFinder = AssemblyFinder.ForSource(configurationAssemblySource); - return settingConfiguration.Settings(new ConfigurationReader(configSection, assemblyFinder, configuration: null)); + return settingConfiguration.Settings(new ConfigurationReader(configSection, assemblyFinder, configuration: null, formatProvider: null)); } /// @@ -178,6 +175,7 @@ public static LoggerConfiguration ConfigurationSection( /// A section name for section which contains a Serilog section. /// A collection of assemblies that contains sinks and other types. /// An object allowing configuration to continue. + [Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")] public static LoggerConfiguration Configuration( this LoggerSettingsConfiguration settingConfiguration, IConfiguration configuration, @@ -188,7 +186,8 @@ public static LoggerConfiguration Configuration( if (configuration == null) throw new ArgumentNullException(nameof(configuration)); if (sectionName == null) throw new ArgumentNullException(nameof(sectionName)); - return settingConfiguration.Settings(new ConfigurationReader(configuration.GetSection(sectionName), assemblies, new ResolutionContext(configuration))); + var readerOptions = new ConfigurationReaderOptions(assemblies) { SectionName = sectionName, FormatProvider = null }; + return Configuration(settingConfiguration, configuration, readerOptions); } /// @@ -198,9 +197,51 @@ public static LoggerConfiguration Configuration( /// A configuration object which contains a Serilog section. /// A collection of assemblies that contains sinks and other types. /// An object allowing configuration to continue. + [Obsolete("Use ReadFrom.Configuration(IConfiguration configuration, ConfigurationReaderOptions readerOptions) instead.")] public static LoggerConfiguration Configuration( this LoggerSettingsConfiguration settingConfiguration, IConfiguration configuration, params Assembly[] assemblies) => Configuration(settingConfiguration, configuration, DefaultSectionName, assemblies); + + /// + /// Reads logger settings from the provided configuration object using the specified context. + /// + /// Logger setting configuration. + /// A configuration object which contains a Serilog section. + /// Options to adjust how the configuration object is processed. + /// An object allowing configuration to continue. + public static LoggerConfiguration Configuration( + this LoggerSettingsConfiguration settingConfiguration, + IConfiguration configuration, + ConfigurationReaderOptions readerOptions = null) + { + var configurationReader = readerOptions switch + { + { ConfigurationAssemblySource: {} } => GetConfigurationReader(configuration, readerOptions, readerOptions.ConfigurationAssemblySource.Value), + { Assemblies: {} } => GetConfigurationReader(configuration, readerOptions, readerOptions.Assemblies), + _ => GetConfigurationReader(configuration, readerOptions ?? new ConfigurationReaderOptions(), readerOptions?.DependencyContext), + }; + return settingConfiguration.Settings(configurationReader); + } + + static ConfigurationReader GetConfigurationReader(IConfiguration configuration, ConfigurationReaderOptions readerOptions, DependencyContext dependencyContext) + { + var assemblyFinder = dependencyContext == null ? AssemblyFinder.Auto() : AssemblyFinder.ForDependencyContext(dependencyContext); + var section = configuration.GetSection(readerOptions.SectionName); + return new ConfigurationReader(section, assemblyFinder, readerOptions.FormatProvider, configuration); + } + + static ConfigurationReader GetConfigurationReader(IConfiguration configuration, ConfigurationReaderOptions readerOptions, ConfigurationAssemblySource source) + { + var assemblyFinder = AssemblyFinder.ForSource(source); + var section = configuration.GetSection(readerOptions.SectionName); + return new ConfigurationReader(section, assemblyFinder, readerOptions.FormatProvider, configuration); + } + + static ConfigurationReader GetConfigurationReader(IConfiguration configuration, ConfigurationReaderOptions readerOptions, IReadOnlyCollection assemblies) + { + var section = configuration.GetSection(readerOptions.SectionName); + return new ConfigurationReader(section, assemblies, new ResolutionContext(configuration, readerOptions.FormatProvider)); + } } diff --git a/src/Serilog.Settings.Configuration/Serilog.Settings.Configuration.csproj b/src/Serilog.Settings.Configuration/Serilog.Settings.Configuration.csproj index bd8809e..da033d1 100644 --- a/src/Serilog.Settings.Configuration/Serilog.Settings.Configuration.csproj +++ b/src/Serilog.Settings.Configuration/Serilog.Settings.Configuration.csproj @@ -28,6 +28,7 @@ + diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs index 828dee1..cd10c3e 100644 --- a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs +++ b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReader.cs @@ -22,11 +22,11 @@ class ConfigurationReader : IConfigurationReader readonly ResolutionContext _resolutionContext; readonly IConfigurationRoot _configurationRoot; - public ConfigurationReader(IConfigurationSection configSection, AssemblyFinder assemblyFinder, IConfiguration configuration = null) + public ConfigurationReader(IConfigurationSection configSection, AssemblyFinder assemblyFinder, IFormatProvider formatProvider, IConfiguration configuration = null) { _section = configSection ?? throw new ArgumentNullException(nameof(configSection)); _configurationAssemblies = LoadConfigurationAssemblies(_section, assemblyFinder); - _resolutionContext = new ResolutionContext(configuration); + _resolutionContext = new ResolutionContext(configuration, formatProvider); _configurationRoot = configuration as IConfigurationRoot; } diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReaderOptions.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReaderOptions.cs new file mode 100644 index 0000000..a4061ae --- /dev/null +++ b/src/Serilog.Settings.Configuration/Settings/Configuration/ConfigurationReaderOptions.cs @@ -0,0 +1,62 @@ +using System.Globalization; +using System.Reflection; +using Microsoft.Extensions.DependencyModel; + +namespace Serilog.Settings.Configuration; + +/// +/// Options to adjust how the configuration object is processed. +/// +public sealed class ConfigurationReaderOptions +{ + /// + /// Initialize a new instance of the class. + /// + /// A collection of assemblies that contains sinks and other types. + /// The argument is null. + /// The argument is empty. + public ConfigurationReaderOptions(params Assembly[] assemblies) + { + Assemblies = assemblies ?? throw new ArgumentNullException(nameof(assemblies)); + if (assemblies.Length == 0) + throw new ArgumentException("The assemblies array must not be empty.", nameof(assemblies)); + } + + /// + /// Initialize a new instance of the class. + /// + /// Prefer the constructor taking explicit assemblies: . It's the only one supporting single-file publishing. + public ConfigurationReaderOptions() : this(dependencyContext: null) + { + } + + /// + /// Initialize a new instance of the class. + /// + /// + /// The dependency context from which sink/enricher packages can be located. If , the platform default will be used. + /// + /// Prefer the constructor taking explicit assemblies: . It's the only one supporting single-file publishing. + public ConfigurationReaderOptions(DependencyContext dependencyContext) => DependencyContext = dependencyContext; + + /// + /// Initialize a new instance of the class. + /// + /// Defines how the package identifies assemblies to scan for sinks and other types. + /// Prefer the constructor taking explicit assemblies: . It's the only one supporting single-file publishing. + public ConfigurationReaderOptions(ConfigurationAssemblySource configurationAssemblySource) => ConfigurationAssemblySource = configurationAssemblySource; + + /// + /// The section name for section which contains a Serilog section. Defaults to Serilog. + /// + public string SectionName { get; init; } = ConfigurationLoggerConfigurationExtensions.DefaultSectionName; + + /// + /// The used when converting strings to other object types. Defaults to the invariant culture. + /// + public IFormatProvider FormatProvider { get; init; } = CultureInfo.InvariantCulture; + + internal Assembly[] Assemblies { get; } + internal DependencyContext DependencyContext { get; } + internal ConfigurationAssemblySource? ConfigurationAssemblySource { get; } +} diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/ResolutionContext.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/ResolutionContext.cs index 1db02a5..8959cda 100644 --- a/src/Serilog.Settings.Configuration/Settings/Configuration/ResolutionContext.cs +++ b/src/Serilog.Settings.Configuration/Settings/Configuration/ResolutionContext.cs @@ -13,13 +13,16 @@ sealed class ResolutionContext readonly IDictionary _declaredFilterSwitches; readonly IConfiguration _appConfiguration; - public ResolutionContext(IConfiguration appConfiguration = null) + public ResolutionContext(IConfiguration appConfiguration = null, IFormatProvider formatProvider = null) { _declaredLevelSwitches = new Dictionary(); _declaredFilterSwitches = new Dictionary(); _appConfiguration = appConfiguration; + FormatProvider = formatProvider; } + public IFormatProvider FormatProvider { get; } + /// /// Looks up a switch in the declared LoggingLevelSwitches /// diff --git a/src/Serilog.Settings.Configuration/Settings/Configuration/StringArgumentValue.cs b/src/Serilog.Settings.Configuration/Settings/Configuration/StringArgumentValue.cs index c15c4b1..89db54d 100644 --- a/src/Serilog.Settings.Configuration/Settings/Configuration/StringArgumentValue.cs +++ b/src/Serilog.Settings.Configuration/Settings/Configuration/StringArgumentValue.cs @@ -155,7 +155,7 @@ public object ConvertTo(Type toType, ResolutionContext resolutionContext) } } - return Convert.ChangeType(argumentValue, toType); + return Convert.ChangeType(argumentValue, toType, resolutionContext.FormatProvider); } internal static Type FindType(string typeName) diff --git a/test/Serilog.Settings.Configuration.Tests/ConfigurationReaderTests.cs b/test/Serilog.Settings.Configuration.Tests/ConfigurationReaderTests.cs index 65cc792..4658f70 100644 --- a/test/Serilog.Settings.Configuration.Tests/ConfigurationReaderTests.cs +++ b/test/Serilog.Settings.Configuration.Tests/ConfigurationReaderTests.cs @@ -1,4 +1,5 @@ -using System.Reflection; +using System.Globalization; +using System.Reflection; using Microsoft.Extensions.Configuration; using Serilog.Events; using Serilog.Formatting; @@ -16,7 +17,8 @@ public ConfigurationReaderTests() { _configurationReader = new ConfigurationReader( JsonStringConfigSource.LoadSection(@"{ 'Serilog': { } }", "Serilog"), - AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies)); + AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies), + CultureInfo.InvariantCulture); } [Fact] @@ -190,7 +192,7 @@ public void MethodsAreSelectedBasedOnCountOfMatchedArgumentsAndThenStringType() [MemberData(nameof(FlatMinimumLevel))] public void FlatMinimumLevelCorrectOneIsEnabledOnLogger(IConfigurationRoot root, LogEventLevel expectedMinimumLevel) { - var reader = new ConfigurationReader(root.GetSection("Serilog"), AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies), root); + var reader = new ConfigurationReader(root.GetSection("Serilog"), AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies), CultureInfo.InvariantCulture, root); var loggerConfig = new LoggerConfiguration(); reader.Configure(loggerConfig); @@ -214,7 +216,7 @@ public void FlatMinimumLevelCorrectOneIsEnabledOnLogger(IConfigurationRoot root, [MemberData(nameof(ObjectMinimumLevel))] public void ObjectMinimumLevelCorrectOneIsEnabledOnLogger(IConfigurationRoot root, LogEventLevel expectedMinimumLevel) { - var reader = new ConfigurationReader(root.GetSection("Serilog"), AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies), root); + var reader = new ConfigurationReader(root.GetSection("Serilog"), AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies), CultureInfo.InvariantCulture, root); var loggerConfig = new LoggerConfiguration(); reader.Configure(loggerConfig); @@ -256,7 +258,7 @@ public void ObjectMinimumLevelCorrectOneIsEnabledOnLogger(IConfigurationRoot roo [MemberData(nameof(MixedMinimumLevel))] public void MixedMinimumLevelCorrectOneIsEnabledOnLogger(IConfigurationRoot root, LogEventLevel expectedMinimumLevel) { - var reader = new ConfigurationReader(root.GetSection("Serilog"), AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies), root); + var reader = new ConfigurationReader(root.GetSection("Serilog"), AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies), CultureInfo.InvariantCulture, root); var loggerConfig = new LoggerConfiguration(); reader.Configure(loggerConfig); @@ -268,7 +270,7 @@ public void MixedMinimumLevelCorrectOneIsEnabledOnLogger(IConfigurationRoot root public void NoConfigurationRootUsedStillValid() { var section = JsonStringConfigSource.LoadSection(@"{ 'Nest': { 'Serilog': { 'MinimumLevel': 'Error' } } }", "Nest"); - var reader = new ConfigurationReader(section.GetSection("Serilog"), AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies), section); + var reader = new ConfigurationReader(section.GetSection("Serilog"), AssemblyFinder.ForSource(ConfigurationAssemblySource.UseLoadedAssemblies), CultureInfo.InvariantCulture, section); var loggerConfig = new LoggerConfiguration(); reader.Configure(loggerConfig); diff --git a/test/Serilog.Settings.Configuration.Tests/ConfigurationSettingsTests.cs b/test/Serilog.Settings.Configuration.Tests/ConfigurationSettingsTests.cs index 94e8ff9..9689c05 100644 --- a/test/Serilog.Settings.Configuration.Tests/ConfigurationSettingsTests.cs +++ b/test/Serilog.Settings.Configuration.Tests/ConfigurationSettingsTests.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Configuration; +using System.Globalization; +using Microsoft.Extensions.Configuration; using Serilog.Core; using Serilog.Events; using Serilog.Settings.Configuration.Tests.Support; @@ -102,7 +103,7 @@ public void ConfigurationAssembliesFromDllScanning() var log = new LoggerConfiguration() .ReadFrom.Configuration( configuration: config, - configurationAssemblySource: ConfigurationAssemblySource.AlwaysScanDllFiles) + readerOptions: new ConfigurationReaderOptions(ConfigurationAssemblySource.AlwaysScanDllFiles)) .CreateLogger(); DummyConsoleSink.Emitted.Clear(); @@ -648,6 +649,50 @@ public void SinkWithStringArrayArgument() Assert.Single(DummyRollingFileSink.Emitted); } + [Theory] + [InlineData(".")] + [InlineData(",")] + [Trait("BugFix", "https://github.com/serilog/serilog-settings-configuration/issues/325")] + public void DestructureNumericNumbers(string numberDecimalSeparator) + { + var originalCulture = Thread.CurrentThread.CurrentCulture; + + var culture = (CultureInfo)CultureInfo.InvariantCulture.Clone(); + culture.NumberFormat.NumberDecimalSeparator = numberDecimalSeparator; + + Thread.CurrentThread.CurrentCulture = culture; + + try + { + var json = @"{ + ""Serilog"": { + ""Using"": [ ""TestDummies"" ], + ""Destructure"": [{ + ""Name"": ""DummyNumbers"", + ""Args"": { + ""floatValue"": 0.1, + ""doubleValue"": 0.2, + ""decimalValue"": 0.3 + } + }] + } + }"; + + DummyPolicy.Current = null; + + ConfigFromJson(json); + + Assert.NotNull(DummyPolicy.Current); + Assert.Equal(0.1f, DummyPolicy.Current.Float); + Assert.Equal(0.2d, DummyPolicy.Current.Double); + Assert.Equal(0.3m, DummyPolicy.Current.Decimal); + } + finally + { + Thread.CurrentThread.CurrentCulture = originalCulture; + } + } + [Fact] public void DestructureWithCollectionsOfTypeArgument() { diff --git a/test/Serilog.Settings.Configuration.Tests/LoggerConfigurationExtensionsTests.cs b/test/Serilog.Settings.Configuration.Tests/LoggerConfigurationExtensionsTests.cs index c022aee..0c76cc3 100644 --- a/test/Serilog.Settings.Configuration.Tests/LoggerConfigurationExtensionsTests.cs +++ b/test/Serilog.Settings.Configuration.Tests/LoggerConfigurationExtensionsTests.cs @@ -96,7 +96,7 @@ public void ReadFromConfigurationDoesNotThrowWhenTryingToCallConfigurationMethod .Build(); _ = new LoggerConfiguration() - .ReadFrom.Configuration(config, "NotSerilog") + .ReadFrom.Configuration(config, new ConfigurationReaderOptions { SectionName = "NotSerilog" }) .CreateLogger(); } diff --git a/test/TestDummies/DummyLoggerConfigurationExtensions.cs b/test/TestDummies/DummyLoggerConfigurationExtensions.cs index 6d97379..7dfccc0 100644 --- a/test/TestDummies/DummyLoggerConfigurationExtensions.cs +++ b/test/TestDummies/DummyLoggerConfigurationExtensions.cs @@ -156,4 +156,17 @@ public static LoggerConfiguration DummyArrayOfType(this LoggerDestructuringConfi CustomStrings = customString, }); } + + public static LoggerConfiguration DummyNumbers(this LoggerDestructuringConfiguration loggerSinkConfiguration, + float floatValue, + double doubleValue, + decimal decimalValue) + { + return loggerSinkConfiguration.With(DummyPolicy.Current = new DummyPolicy + { + Float = floatValue, + Double = doubleValue, + Decimal = decimalValue, + }); + } } diff --git a/test/TestDummies/DummyPolicy.cs b/test/TestDummies/DummyPolicy.cs index cf13832..f289818 100644 --- a/test/TestDummies/DummyPolicy.cs +++ b/test/TestDummies/DummyPolicy.cs @@ -18,6 +18,12 @@ public class DummyPolicy : IDestructuringPolicy public Type Type { get; set; } + public float Float { get; set; } + + public double Double { get; set; } + + public decimal Decimal { get; set; } + public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) { result = null;