Skip to content

Remove handwritten binding logic from Logging.Console; use generator instead - #88067

Merged
layomia merged 7 commits into
dotnet:mainfrom
layomia:binder-gen-rooting
Jul 14, 2023
Merged

Remove handwritten binding logic from Logging.Console; use generator instead#88067
layomia merged 7 commits into
dotnet:mainfrom
layomia:binder-gen-rooting

Conversation

@layomia

Copy link
Copy Markdown
Contributor
Generated code (click to view)
// <auto-generated/>
#nullable enable
/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>internalstaticclassGeneratedConfigurationBinder{/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>publicstaticvoidBind(thisglobal::Microsoft.Extensions.Configuration.IConfigurationconfiguration,global::Microsoft.Extensions.Logging.Console.ConsoleFormatterOptionsobj)=>global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration,refobj,binderOptions:null);/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>publicstaticvoidBind(thisglobal::Microsoft.Extensions.Configuration.IConfigurationconfiguration,global::Microsoft.Extensions.Logging.Console.ConsoleLoggerOptionsobj)=>global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration,refobj,binderOptions:null);/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>publicstaticvoidBind(thisglobal::Microsoft.Extensions.Configuration.IConfigurationconfiguration,global::Microsoft.Extensions.Logging.Console.JsonConsoleFormatterOptionsobj)=>global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration,refobj,binderOptions:null);/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>publicstaticvoidBind(thisglobal::Microsoft.Extensions.Configuration.IConfigurationconfiguration,global::Microsoft.Extensions.Logging.Console.SimpleConsoleFormatterOptionsobj)=>global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration,refobj,binderOptions:null);}namespaceMicrosoft.Extensions.Configuration.Binder.SourceGeneration{usingMicrosoft.Extensions.Configuration;usingMicrosoft.Extensions.Logging;usingMicrosoft.Extensions.Logging.Console;usingSystem;usingSystem.Collections.Generic;usingSystem.Globalization;usingSystem.Text.Encodings.Web;usingSystem.Text.Json;/// <summary>Provide core binding logic.</summary>internalstaticclassCoreBindingHelper{publicstaticvoidBindCore(IConfigurationconfiguration,refConsoleFormatterOptionsobj,BinderOptions?binderOptions){if(objisnull){thrownewArgumentNullException(nameof(obj));}List<string>?temp=null;foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){switch(section.Key){case"IncludeScopes":{if(configuration["IncludeScopes"]isstringstringValue0){obj.IncludeScopes=ParseBool(stringValue0,()=>section.Path)!;}}break;case"TimestampFormat":{obj.TimestampFormat=configuration["TimestampFormat"]!;}break;case"UseUtcTimestamp":{if(configuration["UseUtcTimestamp"]isstringstringValue2){obj.UseUtcTimestamp=ParseBool(stringValue2,()=>section.Path)!;}}break;default:{if(binderOptions?.ErrorOnUnknownConfiguration==true){(temp??=newList<string>()).Add($"'{section.Key}'");}}break;}}if(tempis not null){thrownewInvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(ConsoleFormatterOptions)}: {string.Join(", ",temp)}");}}publicstaticvoidBindCore(IConfigurationconfiguration,refConsoleLoggerOptionsobj,BinderOptions?binderOptions){if(objisnull){thrownewArgumentNullException(nameof(obj));}List<string>?temp=null;foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){switch(section.Key){case"DisableColors":{if(configuration["DisableColors"]isstringstringValue3){obj.DisableColors=ParseBool(stringValue3,()=>section.Path)!;}}break;case"Format":{if(configuration["Format"]isstringstringValue4){obj.Format=ParseConsoleLoggerFormat(stringValue4,()=>section.Path)!;}}break;case"FormatterName":{obj.FormatterName=configuration["FormatterName"]!;}break;case"IncludeScopes":{if(configuration["IncludeScopes"]isstringstringValue6){obj.IncludeScopes=ParseBool(stringValue6,()=>section.Path)!;}}break;case"LogToStandardErrorThreshold":{if(configuration["LogToStandardErrorThreshold"]isstringstringValue7){obj.LogToStandardErrorThreshold=ParseLogLevel(stringValue7,()=>section.Path)!;}}break;case"TimestampFormat":{obj.TimestampFormat=configuration["TimestampFormat"]!;}break;case"UseUtcTimestamp":{if(configuration["UseUtcTimestamp"]isstringstringValue9){obj.UseUtcTimestamp=ParseBool(stringValue9,()=>section.Path)!;}}break;case"QueueFullMode":{if(configuration["QueueFullMode"]isstringstringValue10){obj.QueueFullMode=ParseConsoleLoggerQueueFullMode(stringValue10,()=>section.Path)!;}}break;case"MaxQueueLength":{if(configuration["MaxQueueLength"]isstringstringValue11){obj.MaxQueueLength=ParseInt(stringValue11,()=>section.Path)!;}}break;default:{if(binderOptions?.ErrorOnUnknownConfiguration==true){(temp??=newList<string>()).Add($"'{section.Key}'");}}break;}}if(tempis not null){thrownewInvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(ConsoleLoggerOptions)}: {string.Join(", ",temp)}");}}publicstaticvoidBindCore(IConfigurationconfiguration,refJsonWriterOptionsobj,BinderOptions?binderOptions){List<string>?temp=null;foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){switch(section.Key){case"Encoder":{thrownewInvalidOperationException("Cannot create instance of type 'System.Text.Encodings.Web.JavaScriptEncoder' because it is missing a public instance constructor.");}case"Indented":{if(configuration["Indented"]isstringstringValue12){obj.Indented=ParseBool(stringValue12,()=>section.Path)!;}}break;case"MaxDepth":{if(configuration["MaxDepth"]isstringstringValue13){obj.MaxDepth=ParseInt(stringValue13,()=>section.Path)!;}}break;case"SkipValidation":{if(configuration["SkipValidation"]isstringstringValue14){obj.SkipValidation=ParseBool(stringValue14,()=>section.Path)!;}}break;default:{if(binderOptions?.ErrorOnUnknownConfiguration==true){(temp??=newList<string>()).Add($"'{section.Key}'");}}break;}}if(tempis not null){thrownewInvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(JsonWriterOptions)}: {string.Join(", ",temp)}");}}publicstaticvoidBindCore(IConfigurationconfiguration,refJsonConsoleFormatterOptionsobj,BinderOptions?binderOptions){if(objisnull){thrownewArgumentNullException(nameof(obj));}List<string>?temp=null;foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){switch(section.Key){case"JsonWriterOptions":{if(HasChildren(section)){JsonWriterOptionstemp15=obj.JsonWriterOptions;BindCore(section,reftemp15,binderOptions);obj.JsonWriterOptions=temp15;}}break;case"IncludeScopes":{if(configuration["IncludeScopes"]isstringstringValue16){obj.IncludeScopes=ParseBool(stringValue16,()=>section.Path)!;}}break;case"TimestampFormat":{obj.TimestampFormat=configuration["TimestampFormat"]!;}break;case"UseUtcTimestamp":{if(configuration["UseUtcTimestamp"]isstringstringValue18){obj.UseUtcTimestamp=ParseBool(stringValue18,()=>section.Path)!;}}break;default:{if(binderOptions?.ErrorOnUnknownConfiguration==true){(temp??=newList<string>()).Add($"'{section.Key}'");}}break;}}if(tempis not null){thrownewInvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(JsonConsoleFormatterOptions)}: {string.Join(", ",temp)}");}}publicstaticvoidBindCore(IConfigurationconfiguration,refSimpleConsoleFormatterOptionsobj,BinderOptions?binderOptions){if(objisnull){thrownewArgumentNullException(nameof(obj));}List<string>?temp=null;foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){switch(section.Key){case"ColorBehavior":{if(configuration["ColorBehavior"]isstringstringValue19){obj.ColorBehavior=ParseLoggerColorBehavior(stringValue19,()=>section.Path)!;}}break;case"SingleLine":{if(configuration["SingleLine"]isstringstringValue20){obj.SingleLine=ParseBool(stringValue20,()=>section.Path)!;}}break;case"IncludeScopes":{if(configuration["IncludeScopes"]isstringstringValue21){obj.IncludeScopes=ParseBool(stringValue21,()=>section.Path)!;}}break;case"TimestampFormat":{obj.TimestampFormat=configuration["TimestampFormat"]!;}break;case"UseUtcTimestamp":{if(configuration["UseUtcTimestamp"]isstringstringValue23){obj.UseUtcTimestamp=ParseBool(stringValue23,()=>section.Path)!;}}break;default:{if(binderOptions?.ErrorOnUnknownConfiguration==true){(temp??=newList<string>()).Add($"'{section.Key}'");}}break;}}if(tempis not null){thrownewInvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(SimpleConsoleFormatterOptions)}: {string.Join(", ",temp)}");}}publicstaticboolHasChildren(IConfigurationconfiguration){foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){returntrue;}returnfalse;}publicstaticboolParseBool(stringstringValue,Func<string?>getPath){try{returnbool.Parse(stringValue);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.",exception);}}publicstaticConsoleLoggerFormatParseConsoleLoggerFormat(stringstringValue,Func<string?>getPath){try{return(ConsoleLoggerFormat)Enum.Parse(typeof(ConsoleLoggerFormat),stringValue,ignoreCase:true);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(ConsoleLoggerFormat)}'.",exception);}}publicstaticLogLevelParseLogLevel(stringstringValue,Func<string?>getPath){try{return(LogLevel)Enum.Parse(typeof(LogLevel),stringValue,ignoreCase:true);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(LogLevel)}'.",exception);}}publicstaticConsoleLoggerQueueFullModeParseConsoleLoggerQueueFullMode(stringstringValue,Func<string?>getPath){try{return(ConsoleLoggerQueueFullMode)Enum.Parse(typeof(ConsoleLoggerQueueFullMode),stringValue,ignoreCase:true);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(ConsoleLoggerQueueFullMode)}'.",exception);}}publicstaticintParseInt(stringstringValue,Func<string?>getPath){try{returnint.Parse(stringValue,NumberStyles.Integer,CultureInfo.InvariantCulture);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.",exception);}}publicstaticLoggerColorBehaviorParseLoggerColorBehavior(stringstringValue,Func<string?>getPath){try{return(LoggerColorBehavior)Enum.Parse(typeof(LoggerColorBehavior),stringValue,ignoreCase:true);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(LoggerColorBehavior)}'.",exception);}}}}
Details

@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/area-extensions-logging
See info in area-owners.md if you want to be subscribed.

Issue Details
Generated code (click to view)
// <auto-generated/>
#nullable enable
/// <summary>Generated helper providing an AOT and linking compatible implementation for configuration binding.</summary>internalstaticclassGeneratedConfigurationBinder{/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>publicstaticvoidBind(thisglobal::Microsoft.Extensions.Configuration.IConfigurationconfiguration,global::Microsoft.Extensions.Logging.Console.ConsoleFormatterOptionsobj)=>global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration,refobj,binderOptions:null);/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>publicstaticvoidBind(thisglobal::Microsoft.Extensions.Configuration.IConfigurationconfiguration,global::Microsoft.Extensions.Logging.Console.ConsoleLoggerOptionsobj)=>global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration,refobj,binderOptions:null);/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>publicstaticvoidBind(thisglobal::Microsoft.Extensions.Configuration.IConfigurationconfiguration,global::Microsoft.Extensions.Logging.Console.JsonConsoleFormatterOptionsobj)=>global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration,refobj,binderOptions:null);/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>publicstaticvoidBind(thisglobal::Microsoft.Extensions.Configuration.IConfigurationconfiguration,global::Microsoft.Extensions.Logging.Console.SimpleConsoleFormatterOptionsobj)=>global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration,refobj,binderOptions:null);}namespaceMicrosoft.Extensions.Configuration.Binder.SourceGeneration{usingMicrosoft.Extensions.Configuration;usingMicrosoft.Extensions.Logging;usingMicrosoft.Extensions.Logging.Console;usingSystem;usingSystem.Collections.Generic;usingSystem.Globalization;usingSystem.Text.Encodings.Web;usingSystem.Text.Json;/// <summary>Provide core binding logic.</summary>internalstaticclassCoreBindingHelper{publicstaticvoidBindCore(IConfigurationconfiguration,refConsoleFormatterOptionsobj,BinderOptions?binderOptions){if(objisnull){thrownewArgumentNullException(nameof(obj));}List<string>?temp=null;foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){switch(section.Key){case"IncludeScopes":{if(configuration["IncludeScopes"]isstringstringValue0){obj.IncludeScopes=ParseBool(stringValue0,()=>section.Path)!;}}break;case"TimestampFormat":{obj.TimestampFormat=configuration["TimestampFormat"]!;}break;case"UseUtcTimestamp":{if(configuration["UseUtcTimestamp"]isstringstringValue2){obj.UseUtcTimestamp=ParseBool(stringValue2,()=>section.Path)!;}}break;default:{if(binderOptions?.ErrorOnUnknownConfiguration==true){(temp??=newList<string>()).Add($"'{section.Key}'");}}break;}}if(tempis not null){thrownewInvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(ConsoleFormatterOptions)}: {string.Join(", ",temp)}");}}publicstaticvoidBindCore(IConfigurationconfiguration,refConsoleLoggerOptionsobj,BinderOptions?binderOptions){if(objisnull){thrownewArgumentNullException(nameof(obj));}List<string>?temp=null;foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){switch(section.Key){case"DisableColors":{if(configuration["DisableColors"]isstringstringValue3){obj.DisableColors=ParseBool(stringValue3,()=>section.Path)!;}}break;case"Format":{if(configuration["Format"]isstringstringValue4){obj.Format=ParseConsoleLoggerFormat(stringValue4,()=>section.Path)!;}}break;case"FormatterName":{obj.FormatterName=configuration["FormatterName"]!;}break;case"IncludeScopes":{if(configuration["IncludeScopes"]isstringstringValue6){obj.IncludeScopes=ParseBool(stringValue6,()=>section.Path)!;}}break;case"LogToStandardErrorThreshold":{if(configuration["LogToStandardErrorThreshold"]isstringstringValue7){obj.LogToStandardErrorThreshold=ParseLogLevel(stringValue7,()=>section.Path)!;}}break;case"TimestampFormat":{obj.TimestampFormat=configuration["TimestampFormat"]!;}break;case"UseUtcTimestamp":{if(configuration["UseUtcTimestamp"]isstringstringValue9){obj.UseUtcTimestamp=ParseBool(stringValue9,()=>section.Path)!;}}break;case"QueueFullMode":{if(configuration["QueueFullMode"]isstringstringValue10){obj.QueueFullMode=ParseConsoleLoggerQueueFullMode(stringValue10,()=>section.Path)!;}}break;case"MaxQueueLength":{if(configuration["MaxQueueLength"]isstringstringValue11){obj.MaxQueueLength=ParseInt(stringValue11,()=>section.Path)!;}}break;default:{if(binderOptions?.ErrorOnUnknownConfiguration==true){(temp??=newList<string>()).Add($"'{section.Key}'");}}break;}}if(tempis not null){thrownewInvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(ConsoleLoggerOptions)}: {string.Join(", ",temp)}");}}publicstaticvoidBindCore(IConfigurationconfiguration,refJsonWriterOptionsobj,BinderOptions?binderOptions){List<string>?temp=null;foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){switch(section.Key){case"Encoder":{thrownewInvalidOperationException("Cannot create instance of type 'System.Text.Encodings.Web.JavaScriptEncoder' because it is missing a public instance constructor.");}case"Indented":{if(configuration["Indented"]isstringstringValue12){obj.Indented=ParseBool(stringValue12,()=>section.Path)!;}}break;case"MaxDepth":{if(configuration["MaxDepth"]isstringstringValue13){obj.MaxDepth=ParseInt(stringValue13,()=>section.Path)!;}}break;case"SkipValidation":{if(configuration["SkipValidation"]isstringstringValue14){obj.SkipValidation=ParseBool(stringValue14,()=>section.Path)!;}}break;default:{if(binderOptions?.ErrorOnUnknownConfiguration==true){(temp??=newList<string>()).Add($"'{section.Key}'");}}break;}}if(tempis not null){thrownewInvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(JsonWriterOptions)}: {string.Join(", ",temp)}");}}publicstaticvoidBindCore(IConfigurationconfiguration,refJsonConsoleFormatterOptionsobj,BinderOptions?binderOptions){if(objisnull){thrownewArgumentNullException(nameof(obj));}List<string>?temp=null;foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){switch(section.Key){case"JsonWriterOptions":{if(HasChildren(section)){JsonWriterOptionstemp15=obj.JsonWriterOptions;BindCore(section,reftemp15,binderOptions);obj.JsonWriterOptions=temp15;}}break;case"IncludeScopes":{if(configuration["IncludeScopes"]isstringstringValue16){obj.IncludeScopes=ParseBool(stringValue16,()=>section.Path)!;}}break;case"TimestampFormat":{obj.TimestampFormat=configuration["TimestampFormat"]!;}break;case"UseUtcTimestamp":{if(configuration["UseUtcTimestamp"]isstringstringValue18){obj.UseUtcTimestamp=ParseBool(stringValue18,()=>section.Path)!;}}break;default:{if(binderOptions?.ErrorOnUnknownConfiguration==true){(temp??=newList<string>()).Add($"'{section.Key}'");}}break;}}if(tempis not null){thrownewInvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(JsonConsoleFormatterOptions)}: {string.Join(", ",temp)}");}}publicstaticvoidBindCore(IConfigurationconfiguration,refSimpleConsoleFormatterOptionsobj,BinderOptions?binderOptions){if(objisnull){thrownewArgumentNullException(nameof(obj));}List<string>?temp=null;foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){switch(section.Key){case"ColorBehavior":{if(configuration["ColorBehavior"]isstringstringValue19){obj.ColorBehavior=ParseLoggerColorBehavior(stringValue19,()=>section.Path)!;}}break;case"SingleLine":{if(configuration["SingleLine"]isstringstringValue20){obj.SingleLine=ParseBool(stringValue20,()=>section.Path)!;}}break;case"IncludeScopes":{if(configuration["IncludeScopes"]isstringstringValue21){obj.IncludeScopes=ParseBool(stringValue21,()=>section.Path)!;}}break;case"TimestampFormat":{obj.TimestampFormat=configuration["TimestampFormat"]!;}break;case"UseUtcTimestamp":{if(configuration["UseUtcTimestamp"]isstringstringValue23){obj.UseUtcTimestamp=ParseBool(stringValue23,()=>section.Path)!;}}break;default:{if(binderOptions?.ErrorOnUnknownConfiguration==true){(temp??=newList<string>()).Add($"'{section.Key}'");}}break;}}if(tempis not null){thrownewInvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(SimpleConsoleFormatterOptions)}: {string.Join(", ",temp)}");}}publicstaticboolHasChildren(IConfigurationconfiguration){foreach(IConfigurationSectionsectioninconfiguration.GetChildren()){returntrue;}returnfalse;}publicstaticboolParseBool(stringstringValue,Func<string?>getPath){try{returnbool.Parse(stringValue);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.",exception);}}publicstaticConsoleLoggerFormatParseConsoleLoggerFormat(stringstringValue,Func<string?>getPath){try{return(ConsoleLoggerFormat)Enum.Parse(typeof(ConsoleLoggerFormat),stringValue,ignoreCase:true);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(ConsoleLoggerFormat)}'.",exception);}}publicstaticLogLevelParseLogLevel(stringstringValue,Func<string?>getPath){try{return(LogLevel)Enum.Parse(typeof(LogLevel),stringValue,ignoreCase:true);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(LogLevel)}'.",exception);}}publicstaticConsoleLoggerQueueFullModeParseConsoleLoggerQueueFullMode(stringstringValue,Func<string?>getPath){try{return(ConsoleLoggerQueueFullMode)Enum.Parse(typeof(ConsoleLoggerQueueFullMode),stringValue,ignoreCase:true);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(ConsoleLoggerQueueFullMode)}'.",exception);}}publicstaticintParseInt(stringstringValue,Func<string?>getPath){try{returnint.Parse(stringValue,NumberStyles.Integer,CultureInfo.InvariantCulture);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.",exception);}}publicstaticLoggerColorBehaviorParseLoggerColorBehavior(stringstringValue,Func<string?>getPath){try{return(LoggerColorBehavior)Enum.Parse(typeof(LoggerColorBehavior),stringValue,ignoreCase:true);}catch(Exceptionexception){thrownewInvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(LoggerColorBehavior)}'.",exception);}}}}
Details
Author:layomia
Assignees:layomia
Labels:

area-Extensions-Logging

Milestone:8.0.0

@layomia

Copy link
Copy Markdown
ContributorAuthor

The failing test is due to #88112.

@layomia
layomia marked this pull request as draft June 28, 2023 00:04
@layomialayomia added the blocked Issue/PR is blocked on something - see comments label Jun 28, 2023
@eerhardt

Copy link
Copy Markdown
Member

The failing test is due to #88112.

That was totally a mistake in the test to have different cases. 😊 But at least now we know we have decent test coverage.

@ericstj

ericstj commented Jun 29, 2023

Copy link
Copy Markdown
Member

If you wanted to unblock this you could fix that test to have matching case, the have the fix for #88112 add test case(s).

@layomialayomia removed the blocked Issue/PR is blocked on something - see comments label Jun 29, 2023
@layomia

Copy link
Copy Markdown
ContributorAuthor

Taking Eric's (St. J :) suggestion - #88067 (comment).

@layomia
layomia marked this pull request as ready for review June 29, 2023 17:51
@layomia

layomia commented Jul 12, 2023

Copy link
Copy Markdown
ContributorAuthor
Generated code following #88338 (click to view) ```C# // #nullable enable #pragma warning disable CS0612, CS0618 // Suppress warnings about [Obsolete] member usage in generated code.

///

Generated helper providing an AOT and linking compatible implementation for configuration binding.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
internal static class GeneratedConfigurationBinder
{
/// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.
public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Microsoft.Extensions.Logging.Console.ConsoleFormatterOptions obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, binderOptions: null);

/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, binderOptions: null);
/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Microsoft.Extensions.Logging.Console.JsonConsoleFormatterOptions obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, binderOptions: null);
/// <summary>Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively.</summary>
public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Microsoft.Extensions.Logging.Console.SimpleConsoleFormatterOptions obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.CoreBindingHelper.BindCore(configuration, ref obj, binderOptions: null);

}

namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
using System.Text.Encodings.Web;
using System.Text.Json;

/// <summary>Provide core binding logic.</summary>
[GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
file static class CoreBindingHelper
{
private readonly static Lazy<HashSet<string>> s_configKeys_ConsoleFormatterOptions = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "IncludeScopes", "TimestampFormat", "UseUtcTimestamp" });
private readonly static Lazy<HashSet<string>> s_configKeys_ConsoleLoggerOptions = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "DisableColors", "Format", "FormatterName", "IncludeScopes", "LogToStandardErrorThreshold", "TimestampFormat", "UseUtcTimestamp", "QueueFullMode", "MaxQueueLength" });
private readonly static Lazy<HashSet<string>> s_configKeys_JsonWriterOptions = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Encoder", "Indented", "MaxDepth", "SkipValidation" });
private readonly static Lazy<HashSet<string>> s_configKeys_JsonConsoleFormatterOptions = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "JsonWriterOptions", "IncludeScopes", "TimestampFormat", "UseUtcTimestamp" });
private readonly static Lazy<HashSet<string>> s_configKeys_SimpleConsoleFormatterOptions = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "ColorBehavior", "SingleLine", "IncludeScopes", "TimestampFormat", "UseUtcTimestamp" });
public static void BindCore(IConfiguration configuration, ref ConsoleFormatterOptions obj, BinderOptions? binderOptions)
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
ValidateConfigurationKeys(typeof(ConsoleFormatterOptions), s_configKeys_ConsoleFormatterOptions, configuration, binderOptions);
if (configuration["IncludeScopes"] is string value0)
{
obj.IncludeScopes = ParseBool(value0, () => configuration.GetSection("IncludeScopes").Path);
}
obj.TimestampFormat = configuration["TimestampFormat"]!;
if (configuration["UseUtcTimestamp"] is string value2)
{
obj.UseUtcTimestamp = ParseBool(value2, () => configuration.GetSection("UseUtcTimestamp").Path);
}
}
public static void BindCore(IConfiguration configuration, ref ConsoleLoggerOptions obj, BinderOptions? binderOptions)
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
ValidateConfigurationKeys(typeof(ConsoleLoggerOptions), s_configKeys_ConsoleLoggerOptions, configuration, binderOptions);
if (configuration["DisableColors"] is string value3)
{
obj.DisableColors = ParseBool(value3, () => configuration.GetSection("DisableColors").Path);
}
if (configuration["Format"] is string value4)
{
obj.Format = ParseConsoleLoggerFormat(value4, () => configuration.GetSection("Format").Path);
}
obj.FormatterName = configuration["FormatterName"]!;
if (configuration["IncludeScopes"] is string value6)
{
obj.IncludeScopes = ParseBool(value6, () => configuration.GetSection("IncludeScopes").Path);
}
if (configuration["LogToStandardErrorThreshold"] is string value7)
{
obj.LogToStandardErrorThreshold = ParseLogLevel(value7, () => configuration.GetSection("LogToStandardErrorThreshold").Path);
}
obj.TimestampFormat = configuration["TimestampFormat"]!;
if (configuration["UseUtcTimestamp"] is string value9)
{
obj.UseUtcTimestamp = ParseBool(value9, () => configuration.GetSection("UseUtcTimestamp").Path);
}
if (configuration["QueueFullMode"] is string value10)
{
obj.QueueFullMode = ParseConsoleLoggerQueueFullMode(value10, () => configuration.GetSection("QueueFullMode").Path);
}
if (configuration["MaxQueueLength"] is string value11)
{
obj.MaxQueueLength = ParseInt(value11, () => configuration.GetSection("MaxQueueLength").Path);
}
}
public static void BindCore(IConfiguration configuration, ref JsonWriterOptions obj, BinderOptions? binderOptions)
{
ValidateConfigurationKeys(typeof(JsonWriterOptions), s_configKeys_JsonWriterOptions, configuration, binderOptions);
if (AsConfigWithChildren(configuration.GetSection("Encoder")) is IConfigurationSection section12)
{
throw new InvalidOperationException("Cannot create instance of type 'System.Text.Encodings.Web.JavaScriptEncoder' because it is missing a public instance constructor.");
}
if (configuration["Indented"] is string value13)
{
obj.Indented = ParseBool(value13, () => configuration.GetSection("Indented").Path);
}
if (configuration["MaxDepth"] is string value14)
{
obj.MaxDepth = ParseInt(value14, () => configuration.GetSection("MaxDepth").Path);
}
if (configuration["SkipValidation"] is string value15)
{
obj.SkipValidation = ParseBool(value15, () => configuration.GetSection("SkipValidation").Path);
}
}
public static void BindCore(IConfiguration configuration, ref JsonConsoleFormatterOptions obj, BinderOptions? binderOptions)
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
ValidateConfigurationKeys(typeof(JsonConsoleFormatterOptions), s_configKeys_JsonConsoleFormatterOptions, configuration, binderOptions);
if (AsConfigWithChildren(configuration.GetSection("JsonWriterOptions")) is IConfigurationSection section16)
{
JsonWriterOptions temp17 = obj.JsonWriterOptions;
var temp18 = new JsonWriterOptions();
BindCore(section16, ref temp18, binderOptions);
obj.JsonWriterOptions = temp18;
temp17 = temp18;
}
if (configuration["IncludeScopes"] is string value19)
{
obj.IncludeScopes = ParseBool(value19, () => configuration.GetSection("IncludeScopes").Path);
}
obj.TimestampFormat = configuration["TimestampFormat"]!;
if (configuration["UseUtcTimestamp"] is string value21)
{
obj.UseUtcTimestamp = ParseBool(value21, () => configuration.GetSection("UseUtcTimestamp").Path);
}
}
public static void BindCore(IConfiguration configuration, ref SimpleConsoleFormatterOptions obj, BinderOptions? binderOptions)
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
ValidateConfigurationKeys(typeof(SimpleConsoleFormatterOptions), s_configKeys_SimpleConsoleFormatterOptions, configuration, binderOptions);
if (configuration["ColorBehavior"] is string value22)
{
obj.ColorBehavior = ParseLoggerColorBehavior(value22, () => configuration.GetSection("ColorBehavior").Path);
}
if (configuration["SingleLine"] is string value23)
{
obj.SingleLine = ParseBool(value23, () => configuration.GetSection("SingleLine").Path);
}
if (configuration["IncludeScopes"] is string value24)
{
obj.IncludeScopes = ParseBool(value24, () => configuration.GetSection("IncludeScopes").Path);
}
obj.TimestampFormat = configuration["TimestampFormat"]!;
if (configuration["UseUtcTimestamp"] is string value26)
{
obj.UseUtcTimestamp = ParseBool(value26, () => configuration.GetSection("UseUtcTimestamp").Path);
}
}
/// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
{
if (binderOptions?.ErrorOnUnknownConfiguration is true)
{
List<string>? temp = null;
foreach (IConfigurationSection section in configuration.GetChildren())
{
if (!keys.Value.Contains(section.Key))
{
(temp ??= new List<string>()).Add($"'{section.Key}'");
}
}
if (temp is not null)
{
throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
}
}
}
public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
{
foreach (IConfigurationSection _ in configuration.GetChildren())
{
return configuration;
}
return null;
}
public static bool ParseBool(string value, Func<string?> getPath)
{
try
{
return bool.Parse(value);
}
catch (Exception exception)
{
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.", exception);
}
}
public static ConsoleLoggerFormat ParseConsoleLoggerFormat(string value, Func<string?> getPath)
{
try
{
return (ConsoleLoggerFormat)Enum.Parse(typeof(ConsoleLoggerFormat), value, ignoreCase: true);
}
catch (Exception exception)
{
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(ConsoleLoggerFormat)}'.", exception);
}
}
public static LogLevel ParseLogLevel(string value, Func<string?> getPath)
{
try
{
return (LogLevel)Enum.Parse(typeof(LogLevel), value, ignoreCase: true);
}
catch (Exception exception)
{
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(LogLevel)}'.", exception);
}
}
public static ConsoleLoggerQueueFullMode ParseConsoleLoggerQueueFullMode(string value, Func<string?> getPath)
{
try
{
return (ConsoleLoggerQueueFullMode)Enum.Parse(typeof(ConsoleLoggerQueueFullMode), value, ignoreCase: true);
}
catch (Exception exception)
{
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(ConsoleLoggerQueueFullMode)}'.", exception);
}
}
public static int ParseInt(string value, Func<string?> getPath)
{
try
{
return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
}
catch (Exception exception)
{
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception);
}
}
public static LoggerColorBehavior ParseLoggerColorBehavior(string value, Func<string?> getPath)
{
try
{
return (LoggerColorBehavior)Enum.Parse(typeof(LoggerColorBehavior), value, ignoreCase: true);
}
catch (Exception exception)
{
throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(LoggerColorBehavior)}'.", exception);
}
}
}

}

</details>

@layomia
layomia requested a review from eerhardtJuly 12, 2023 19:06

@eerhardteerhardt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking really good, @layomia.

@tarekghtarekgh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modulo @eerhardt comments, LGTM.

@layomia
layomiaforce-pushed the binder-gen-rooting branch from 23c67f8 to 63d7519CompareJuly 13, 2023 21:07
Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>

@eerhardteerhardt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks @layomia!

@eiriktsarpaliseiriktsarpalis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great to see all this bespoke code being removed 👍

@layomia

Copy link
Copy Markdown
ContributorAuthor

Failing checks unrelated; check with running indicator appears to be complete -https://dev.azure.com/dnceng-public/public/_build/results?buildId=339049&view=logs&jobId=f02b8cf9-dd4d-54fc-c292-2bb1d305b019.

@layomia
layomia merged commit e264ba7 into dotnet:mainJul 14, 2023
@ghostghost locked as resolved and limited conversation to collaborators Aug 13, 2023
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@layomia@eerhardt@ericstj@eiriktsarpalis@tarekgh