Remove handwritten binding logic from Logging.Console; use generator instead (#88067)
authorLayomi Akinrinade <laakinri@microsoft.com>
Fri, 14 Jul 2023 17:16:27 +0000 (10:16 -0700)
committerGitHub <noreply@github.com>
Fri, 14 Jul 2023 17:16:27 +0000 (10:16 -0700)
* Remove handwritten binding logic from Logging.Console; use generator instead

* Address feedback

* Update test

* Revert "Update test"

This reverts commit fa73b4edcd4a67ad195ab30a405e7f316ae34e5e.

* Remove NoWarn for obsolete members; handled by emitted code

* Address feedback

* Apply suggestions from code review

Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>
---------

Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>
src/libraries/Microsoft.Extensions.Logging.Configuration/src/LoggerFilterConfigureOptions.cs
src/libraries/Microsoft.Extensions.Logging.Configuration/src/Microsoft.Extensions.Logging.Configuration.csproj
src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleFormatterOptions.cs
src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerConfigureOptions.cs
src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerExtensions.Obsolete.cs
src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerOptions.cs
src/libraries/Microsoft.Extensions.Logging.Console/src/JsonConsoleFormatterOptions.cs
src/libraries/Microsoft.Extensions.Logging.Console/src/Microsoft.Extensions.Logging.Console.csproj
src/libraries/Microsoft.Extensions.Logging.Console/src/SimpleConsoleFormatterOptions.cs

index 8a4507c..6afe56f 100644 (file)
@@ -30,7 +30,7 @@ namespace Microsoft.Extensions.Logging
                 return;
             }
 
-            options.CaptureScopes = GetCaptureScopesValue(options);
+            options.CaptureScopes = _configuration.GetValue(nameof(options.CaptureScopes), options.CaptureScopes);
 
             foreach (IConfigurationSection configurationSection in _configuration.GetChildren())
             {
@@ -50,8 +50,6 @@ namespace Microsoft.Extensions.Logging
                     }
                 }
             }
-
-            bool GetCaptureScopesValue(LoggerFilterOptions options) => _configuration.GetValue(nameof(options.CaptureScopes), options.CaptureScopes);
         }
 
         private static void LoadRules(LoggerFilterOptions options, IConfigurationSection configurationSection, string? logger)
index fa787ba..545e286 100644 (file)
@@ -37,7 +37,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Configuration.Binder\gen\Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="true" PrivateAssets="All" />
+    <ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Configuration.Binder\gen\Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" PrivateAssets="All" />
   </ItemGroup>
 
 </Project>
index 408afda..2b3d012 100644 (file)
@@ -32,22 +32,6 @@ namespace Microsoft.Extensions.Logging.Console
         /// </summary>
         public bool UseUtcTimestamp { get; set; }
 
-        internal virtual void Configure(IConfiguration configuration)
-        {
-            if (ConsoleLoggerOptions.ParseBool(configuration, nameof(IncludeScopes), out bool includeScopes))
-            {
-                IncludeScopes = includeScopes;
-            }
-
-            if (configuration[nameof(TimestampFormat)] is string timestampFormat)
-            {
-                TimestampFormat = timestampFormat;
-            }
-
-            if (ConsoleLoggerOptions.ParseBool(configuration, nameof(UseUtcTimestamp), out bool useUtcTimestamp))
-            {
-                UseUtcTimestamp = useUtcTimestamp;
-            }
-        }
+        internal virtual void Configure(IConfiguration configuration) => configuration.Bind(this);
     }
 }
index dc4b98b..b8cd54a 100644 (file)
@@ -26,6 +26,6 @@ namespace Microsoft.Extensions.Logging
             _configuration = providerConfiguration.Configuration;
         }
 
-        public void Configure(ConsoleLoggerOptions options) => options.Configure(_configuration);
+        public void Configure(ConsoleLoggerOptions options) => _configuration.Bind(options);
     }
 }
index 3ddc458..4e8d31a 100644 (file)
@@ -87,14 +87,14 @@ namespace Microsoft.Extensions.Logging
 
             IChangeToken IOptionsChangeTokenSource<ConsoleLoggerOptions>.GetChangeToken() => _settings.ChangeToken ?? NullChangeToken.Instance;
 
-            string IOptionsChangeTokenSource<ConsoleLoggerOptions>.Name => Microsoft.Extensions.Options.Options.DefaultName;
+            string IOptionsChangeTokenSource<ConsoleLoggerOptions>.Name => Options.Options.DefaultName;
 
             void IConfigureOptions<ConsoleLoggerOptions>.Configure(ConsoleLoggerOptions options)
             {
                 options.IncludeScopes = _settings.IncludeScopes;
                 if (_settings is ConfigurationConsoleLoggerSettings configSettings)
                 {
-                    options.Configure(configSettings._configuration);
+                    configSettings._configuration.Bind(options);
                 }
                 else if (_settings is ConsoleLoggerSettings consoleSettings)
                 {
@@ -105,7 +105,7 @@ namespace Microsoft.Extensions.Logging
             internal static OptionsMonitor<ConsoleLoggerOptions> GetOptionsMonitor(IConsoleLoggerSettings settings)
             {
                 ConsoleLoggerSettingsAdapter adapter = new(settings);
-                OptionsFactory<ConsoleLoggerOptions> factory = new( new IConfigureOptions<ConsoleLoggerOptions>[] { adapter }, Array.Empty<IPostConfigureOptions<ConsoleLoggerOptions>>());
+                OptionsFactory<ConsoleLoggerOptions> factory = new(new IConfigureOptions<ConsoleLoggerOptions>[] { adapter }, Array.Empty<IPostConfigureOptions<ConsoleLoggerOptions>>());
                 IOptionsChangeTokenSource<ConsoleLoggerOptions>[] sources = new IOptionsChangeTokenSource<ConsoleLoggerOptions>[] { adapter };
                 OptionsCache<ConsoleLoggerOptions> cache = new();
 
index 8b833ad..69704e4 100644 (file)
@@ -2,8 +2,6 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
-using System.Globalization;
-using Microsoft.Extensions.Configuration;
 
 namespace Microsoft.Extensions.Logging.Console
 {
@@ -102,146 +100,5 @@ namespace Microsoft.Extensions.Logging.Console
                 _maxQueuedMessages = value;
             }
         }
-
-        internal void Configure(IConfiguration configuration)
-        {
-#pragma warning disable CS0618 // Type or member is obsolete
-            if (ParseBool(configuration, nameof(DisableColors), out bool disableColors))
-            {
-                DisableColors = disableColors;
-            }
-#pragma warning restore CS0618 // Type or member is obsolete
-
-#pragma warning disable CS0618 // Type or member is obsolete
-            if (ParseEnum(configuration, nameof(Format), out ConsoleLoggerFormat format))
-            {
-                Format = format;
-            }
-#pragma warning restore CS0618 // Type or member is obsolete
-
-            if (configuration[nameof(FormatterName)] is string formatterName)
-            {
-                FormatterName = formatterName;
-            }
-
-#pragma warning disable CS0618 // Type or member is obsolete
-            if (ParseBool(configuration, nameof(IncludeScopes), out bool includeScopes))
-            {
-                IncludeScopes = includeScopes;
-            }
-#pragma warning restore CS0618 // Type or member is obsolete
-
-            if (ParseEnum(configuration, nameof(LogToStandardErrorThreshold), out LogLevel logToStandardErrorThreshold))
-            {
-                LogToStandardErrorThreshold = logToStandardErrorThreshold;
-            }
-
-            if (ParseInt(configuration, nameof(MaxQueueLength), out int maxQueueLength))
-            {
-                MaxQueueLength = maxQueueLength;
-            }
-
-            if (ParseEnum(configuration, nameof(QueueFullMode), out ConsoleLoggerQueueFullMode queueFullMode))
-            {
-                QueueFullMode = queueFullMode;
-            }
-
-#pragma warning disable CS0618 // Type or member is obsolete
-            if (configuration[nameof(TimestampFormat)] is string timestampFormat)
-            {
-                TimestampFormat = timestampFormat;
-            }
-#pragma warning restore CS0618 // Type or member is obsolete
-
-#pragma warning disable CS0618 // Type or member is obsolete
-            if (ParseBool(configuration, nameof(UseUtcTimestamp), out bool useUtcTimestamp))
-            {
-                UseUtcTimestamp = useUtcTimestamp;
-            }
-#pragma warning restore CS0618 // Type or member is obsolete
-        }
-
-        /// <summary>
-        /// Parses the configuration value at the specified key into a bool.
-        /// </summary>
-        /// <returns>true if the value was successfully found and parsed. false if the key wasn't found.</returns>
-        /// <exception cref="InvalidOperationException">Thrown when invalid data was found at the specified configuration key.</exception>
-        internal static bool ParseBool(IConfiguration configuration, string key, out bool value)
-        {
-            if (configuration[key] is string valueString)
-            {
-                try
-                {
-                    value = bool.Parse(valueString);
-                    return true;
-                }
-                catch (Exception e)
-                {
-                    ThrowInvalidConfigurationException(configuration, key, typeof(bool), e);
-                }
-            }
-
-            value = default;
-            return false;
-        }
-
-        /// <summary>
-        /// Parses the configuration value at the specified key into an enum.
-        /// </summary>
-        /// <returns>true if the value was successfully found and parsed. false if the key wasn't found.</returns>
-        /// <exception cref="InvalidOperationException">Thrown when invalid data was found at the specified configuration key.</exception>
-        internal static bool ParseEnum<T>(IConfiguration configuration, string key, out T value) where T : struct
-        {
-            if (configuration[key] is string valueString)
-            {
-                try
-                {
-                    value =
-#if NETFRAMEWORK || NETSTANDARD2_0
-                        (T)Enum.Parse(typeof(T), valueString, ignoreCase: true);
-#else
-                        Enum.Parse<T>(valueString, ignoreCase: true);
-#endif
-                    return true;
-                }
-                catch (Exception e)
-                {
-                    ThrowInvalidConfigurationException(configuration, key, typeof(T), e);
-                }
-            }
-
-            value = default;
-            return false;
-        }
-
-        /// <summary>
-        /// Parses the configuration value at the specified key into an int.
-        /// </summary>
-        /// <returns>true if the value was successfully found and parsed. false if the key wasn't found.</returns>
-        /// <exception cref="InvalidOperationException">Thrown when invalid data was found at the specified configuration key.</exception>
-        internal static bool ParseInt(IConfiguration configuration, string key, out int value)
-        {
-            if (configuration[key] is string valueString)
-            {
-                try
-                {
-                    value = int.Parse(valueString, NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
-                    return true;
-                }
-                catch (Exception e)
-                {
-                    ThrowInvalidConfigurationException(configuration, key, typeof(int), e);
-                }
-            }
-
-            value = default;
-            return false;
-        }
-
-        private static void ThrowInvalidConfigurationException(IConfiguration configuration, string key, Type valueType, Exception innerException)
-        {
-            IConfigurationSection section = configuration.GetSection(key);
-            throw new InvalidOperationException(SR.Format(SR.InvalidConfigurationData, section.Path, valueType), innerException);
-        }
     }
 }
index 2bdf51c..2a9d4e5 100644 (file)
@@ -21,31 +21,6 @@ namespace Microsoft.Extensions.Logging.Console
         /// </summary>
         public JsonWriterOptions JsonWriterOptions { get; set; }
 
-        internal override void Configure(IConfiguration configuration)
-        {
-            base.Configure(configuration);
-
-            if (configuration.GetSection(nameof(JsonWriterOptions)) is IConfigurationSection jsonWriterOptionsConfig)
-            {
-                JsonWriterOptions jsonWriterOptions = JsonWriterOptions;
-
-                if (ConsoleLoggerOptions.ParseBool(jsonWriterOptionsConfig, nameof(JsonWriterOptions.Indented), out bool indented))
-                {
-                    jsonWriterOptions.Indented = indented;
-                }
-
-                if (ConsoleLoggerOptions.ParseInt(jsonWriterOptionsConfig, nameof(JsonWriterOptions.MaxDepth), out int maxDepth))
-                {
-                    jsonWriterOptions.MaxDepth = maxDepth;
-                }
-
-                if (ConsoleLoggerOptions.ParseBool(jsonWriterOptionsConfig, nameof(JsonWriterOptions.SkipValidation), out bool skipValidation))
-                {
-                    jsonWriterOptions.SkipValidation = skipValidation;
-                }
-
-                JsonWriterOptions = jsonWriterOptions;
-            }
-        }
+        internal override void Configure(IConfiguration configuration) => configuration.Bind(this);
     }
 }
index ed78c7d..8cec9d1 100644 (file)
@@ -7,29 +7,24 @@
     <DefineConstants>$(DefineConstants);NO_SUPPRESS_GC_TRANSITION</DefineConstants>
     <IncludePlatformAttributes>true</IncludePlatformAttributes>
     <IsPackable>true</IsPackable>
+    <EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
+    <!-- M.E.Configuration.Binder.SourceGeneration: JavaScriptEncoder not supported; no logic generated which is okay. Remove this when https://github.com/dotnet/runtime/issues/88865 is fixed.  -->
+    <NoWarn>$(NoWarn);SYSLIB1100</NoWarn>
     <PackageDescription>Console logger provider implementation for Microsoft.Extensions.Logging.</PackageDescription>
   </PropertyGroup>
 
   <ItemGroup>
-    <Compile Include="$(CommonPath)Extensions\Logging\NullExternalScopeProvider.cs"
-             Link="Common\src\Extensions\Logging\NullExternalScopeProvider.cs" />
-    <Compile Include="$(CommonPath)Extensions\Logging\NullScope.cs"
-             Link="Common\src\Extensions\Logging\NullScope.cs" />
-    <Compile Include="$(CommonPath)System\Text\Json\PooledByteBufferWriter.cs"
-             Link="Common\System\Text\Json\PooledByteBufferWriter.cs" />
-    <Compile Include="$(CommonPath)System\ThrowHelper.cs"
-             Link="Common\System\ThrowHelper.cs" />
+    <Compile Include="$(CommonPath)Extensions\Logging\NullExternalScopeProvider.cs" Link="Common\src\Extensions\Logging\NullExternalScopeProvider.cs" />
+    <Compile Include="$(CommonPath)Extensions\Logging\NullScope.cs" Link="Common\src\Extensions\Logging\NullScope.cs" />
+    <Compile Include="$(CommonPath)System\Text\Json\PooledByteBufferWriter.cs" Link="Common\System\Text\Json\PooledByteBufferWriter.cs" />
+    <Compile Include="$(CommonPath)System\ThrowHelper.cs" Link="Common\System\ThrowHelper.cs" />
   </ItemGroup>
 
   <ItemGroup>
-    <Compile Include="$(CommonPath)Interop\Windows\Interop.Libraries.cs"
-             Link="Common\Interop\Windows\Interop.Libraries.cs" />
-    <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetConsoleMode.cs"
-             Link="Common\Interop\Windows\Interop.GetConsoleMode.cs" />
-    <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetStdHandle.cs"
-             Link="Common\Interop\Windows\Interop.GetStdHandle.cs" />
-    <Compile Include="$(CommonPath)System\Console\ConsoleUtils.cs"
-             Link="Common\System\Console\ConsoleUtils.cs" />
+    <Compile Include="$(CommonPath)Interop\Windows\Interop.Libraries.cs" Link="Common\Interop\Windows\Interop.Libraries.cs" />
+    <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetConsoleMode.cs" Link="Common\Interop\Windows\Interop.GetConsoleMode.cs" />
+    <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetStdHandle.cs" Link="Common\Interop\Windows\Interop.GetStdHandle.cs" />
+    <Compile Include="$(CommonPath)System\Console\ConsoleUtils.cs" Link="Common\System\Console\ConsoleUtils.cs" />
   </ItemGroup>
 
   <ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
@@ -67,4 +62,8 @@
     <Reference Include="System.Runtime" />
   </ItemGroup>
 
+  <ItemGroup>
+    <ProjectReference Include="$(LibrariesProjectRoot)Microsoft.Extensions.Configuration.Binder\gen\Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" PrivateAssets="All" />
+  </ItemGroup>
+
 </Project>
index d31efbe..326fb16 100644 (file)
@@ -25,19 +25,6 @@ namespace Microsoft.Extensions.Logging.Console
         /// </summary>
         public bool SingleLine { get; set; }
 
-        internal override void Configure(IConfiguration configuration)
-        {
-            base.Configure(configuration);
-
-            if (ConsoleLoggerOptions.ParseEnum(configuration, nameof(ColorBehavior), out LoggerColorBehavior colorBehavior))
-            {
-                ColorBehavior = colorBehavior;
-            }
-
-            if (ConsoleLoggerOptions.ParseBool(configuration, nameof(SingleLine), out bool singleLine))
-            {
-                SingleLine = singleLine;
-            }
-        }
+        internal override void Configure(IConfiguration configuration) => configuration.Bind(this);
     }
 }