From 751b1d40c960c6dac6830ab03e1e32e914a8d1bc Mon Sep 17 00:00:00 2001 From: rosebyte Date: Thu, 6 Aug 2026 13:43:06 +0200 Subject: [PATCH] [wasm][R2R] Request flat layout for composite image on WebAssembly (#131354) # Honour ErrorOnUnknownConfiguration on value conversion fail Fixes #98231 ## Problem `BinderOptions.ErrorOnUnknownConfiguration` is documented as controlling whether the binder throws "when converting a value", but it was only honoured on some of the paths that can fail: | Failure | Flag honoured? | |---|---| | Unknown configuration key | Yes | | Leaf value with no `TypeConverter` at all | Yes | | Collection item that fails to convert | Yes | | **Leaf value whose `TypeConverter` throws** | **No, always threw** | So a single malformed value in an otherwise valid configuration source would tear down binding even for callers that had deliberately left the flag at its default: ```csharp // appsettings.json: { "Timeout": "not-a-number" } var options = config.Get(); // threw InvalidOperationException ``` This is inconsistent both with the documented contract on the property and with the sibling "no converter" case a few lines away in the same method, which already returned quietly. ## Fix Gate the rethrow on the flag, in both the reflection binder and the source generator. ### Reflection binder `BindInstance` no longer rethrows the conversion error unconditionally; it returns and leaves the binding point untouched, so the member keeps whatever value it already had. ### Source generator The emitted `ParseX(value, path)` helpers become `TryParseX(value, path, errorOnFailedBinding, out result)`: ```csharp public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); return true; } catch when (!errorOnFailedBinding) { result = default; return false; } catch (Exception exception) { throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } ``` Call sites pass `binderOptions?.ErrorOnUnknownConfiguration is true`, except for two cases that must always report the failure: - `GetValueCore`, since `GetValue` has no `BinderOptions` overload. - Constructor parameters with no declared default, which are unsatisfiable either way. These keep throwing the accurate `Failed to convert configuration value ...` rather than degrading to `... has no matching config`. A try/catch at each call site was considered instead, but it would also have swallowed nested binding errors in the dictionary case; a `Func<>`-based helper would have allocated. ## Behaviour change This is a breaking change and will need a breaking-change doc. | Scenario | Before | After | |---|---|---| | `Bind` / `Get` with an unconvertible scalar, default options | throws | member keeps its existing value | | `GetSection("x").Get()` with a bad value | throws | `default(int)` | | Same, with `ErrorOnUnknownConfiguration = true` | throws | throws (unchanged) | | `GetValue` with a bad value | throws | throws (unchanged) | | Required constructor parameter with a bad value | throws | throws (unchanged) | | Constructor parameter with a declared default and a bad value | throws | falls back to the default | The `Get`/`Bind` versus `GetValue` asymmetry is deliberate and follows the design agreed in the issue, but it is user-visible. ## Also in this change - Fixes a latent generator bug: a primitive section with an empty value used to fall through `GetCore` to `throw new NotSupportedException("Unable to bind to type ...: generator did not detect the type as input.")`. It now returns `null`, matching the reflection binder. - Fixes a hard-coded path separator in `GeneratorTests.Helpers.cs` that stopped `/p:UpdateBaselines=true` working on non-Windows hosts. - Un-gates two `CollectionsBindingWithErrorOnUnknownConfiguration` tests that were restricted to the reflection binder; they now pass under source generation too. ## Testing - 4 existing tests that asserted the old unconditional throw now opt in with `ErrorOnUnknownConfiguration = true`. - New regression tests cover both flag states, the `GetValue` carve-out, and constructor parameters with and without declared defaults. All run in both binder modes. - 111 of the 120 generator baselines regenerated (`netcoreapp` and `net462`, `Version0` and `Version1`). Some `net462` `Version0` files additionally pick up unrelated drift corrections that had accumulated on `main`. ``` Microsoft.Extensions.Configuration.Binder.Tests 356 passed, 0 failed Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests 433 passed, 0 failed, 26 skipped ``` --- .../gen/Emitter/CoreBindingHelpers.cs | 142 +++-- .../gen/Emitter/Helpers.cs | 3 + .../gen/Specs/TypeIndex.cs | 6 +- .../src/ConfigurationBinder.cs | 38 +- .../ConfigurationBinderTests.TestClasses.cs | 9 +- .../tests/Common/ConfigurationBinderTests.cs | 53 +- .../Version0/Bind.generated.txt | 105 ++-- .../Version0/Bind_Instance.generated.txt | 101 ++-- .../Bind_Instance_BinderOptions.generated.txt | 101 ++-- .../Version0/Bind_Key_Instance.generated.txt | 101 ++-- ...ind_ParseTypeFromMethodParam.generated.txt | 18 +- .../Version0/Get.generated.txt | 127 +++-- .../Version0/GetValue.generated.txt | 106 ++-- .../Version0/GetValue_T_Key.generated.txt | 37 +- .../GetValue_T_Key_DefaultValue.generated.txt | 37 +- .../GetValue_TypeOf_Key.generated.txt | 37 +- ...alue_TypeOf_Key_DefaultValue.generated.txt | 37 +- .../Version0/Get_PrimitivesOnly.generated.txt | 77 ++- .../Version0/Get_T.generated.txt | 116 ++-- .../Get_T_BinderOptions.generated.txt | 116 ++-- .../Version0/Get_TypeOf.generated.txt | 41 +- .../Get_TypeOf_BinderOptions.generated.txt | 41 +- .../Version1/Bind.generated.txt | 60 ++- .../Version1/Bind_Instance.generated.txt | 60 ++- .../Bind_Instance_BinderOptions.generated.txt | 60 ++- .../Version1/Bind_Key_Instance.generated.txt | 60 ++- .../Version1/Get.generated.txt | 78 +-- .../Version1/GetValue.generated.txt | 60 ++- .../Version1/GetValue_T_Key.generated.txt | 15 +- .../GetValue_T_Key_DefaultValue.generated.txt | 15 +- .../GetValue_TypeOf_Key.generated.txt | 15 +- ...alue_TypeOf_Key_DefaultValue.generated.txt | 15 +- .../Version1/Get_PrimitivesOnly.generated.txt | 45 +- .../Version1/Get_T.generated.txt | 72 +-- .../Get_T_BinderOptions.generated.txt | 72 +-- .../Version1/Get_TypeOf.generated.txt | 14 +- .../Get_TypeOf_BinderOptions.generated.txt | 14 +- .../Version0/BindConfiguration.generated.txt | 73 ++- ...gurationWithConfigureActions.generated.txt | 73 ++- .../Version0/Bind_T.generated.txt | 75 ++- .../Bind_T_BinderOptions.generated.txt | 73 ++- .../Version1/BindConfiguration.generated.txt | 36 +- ...gurationWithConfigureActions.generated.txt | 36 +- .../Version1/Bind_T.generated.txt | 36 +- .../Bind_T_BinderOptions.generated.txt | 36 +- .../Version0/Configure_T.generated.txt | 110 ++-- .../Configure_T_BinderOptions.generated.txt | 110 ++-- .../Version0/Configure_T_name.generated.txt | 110 ++-- ...nfigure_T_name_BinderOptions.generated.txt | 110 ++-- .../Version1/Configure_T.generated.txt | 66 +-- .../Configure_T_BinderOptions.generated.txt | 66 +-- .../Version1/Configure_T_name.generated.txt | 66 +-- ...nfigure_T_name_BinderOptions.generated.txt | 66 +-- .../net462/Version0/Collections.generated.txt | 140 +++-- ...DefaultConstructorParameters.generated.txt | 228 ++++++-- .../Version0/EmptyConfigType.generated.txt | 23 +- .../net462/Version0/Primitives.generated.txt | 496 +++++++++++++----- .../Version0/UnsupportedTypes.generated.txt | 104 ++-- .../net462/Version1/Collections.generated.txt | 84 +-- ...DefaultConstructorParameters.generated.txt | 138 +++-- .../net462/Version1/Primitives.generated.txt | 382 +++++++++----- .../Version1/UnsupportedTypes.generated.txt | 56 +- .../Version0/Bind.generated.txt | 68 +-- .../Version0/Bind_Instance.generated.txt | 68 +-- .../Bind_Instance_BinderOptions.generated.txt | 68 +-- .../Version0/Bind_Key_Instance.generated.txt | 68 +-- .../Version0/Get.generated.txt | 88 ++-- .../Version0/GetValue.generated.txt | 60 ++- .../Version0/GetValue_T_Key.generated.txt | 15 +- .../GetValue_T_Key_DefaultValue.generated.txt | 15 +- .../GetValue_TypeOf_Key.generated.txt | 15 +- ...alue_TypeOf_Key_DefaultValue.generated.txt | 15 +- .../Version0/Get_PrimitivesOnly.generated.txt | 45 +- .../Version0/Get_T.generated.txt | 80 +-- .../Get_T_BinderOptions.generated.txt | 80 +-- .../Version0/Get_TypeOf.generated.txt | 22 +- .../Get_TypeOf_BinderOptions.generated.txt | 22 +- .../Version1/Bind.generated.txt | 60 ++- .../Version1/Bind_Instance.generated.txt | 60 ++- .../Bind_Instance_BinderOptions.generated.txt | 60 ++- .../Version1/Bind_Key_Instance.generated.txt | 60 ++- .../Version1/Get.generated.txt | 78 +-- .../Version1/GetValue.generated.txt | 60 ++- .../Version1/GetValue_T_Key.generated.txt | 15 +- .../GetValue_T_Key_DefaultValue.generated.txt | 15 +- .../GetValue_TypeOf_Key.generated.txt | 15 +- ...alue_TypeOf_Key_DefaultValue.generated.txt | 15 +- .../Version1/Get_PrimitivesOnly.generated.txt | 45 +- .../Version1/Get_T.generated.txt | 72 +-- .../Get_T_BinderOptions.generated.txt | 72 +-- .../Version1/Get_TypeOf.generated.txt | 14 +- .../Get_TypeOf_BinderOptions.generated.txt | 14 +- .../Version0/BindConfiguration.generated.txt | 50 +- ...gurationWithConfigureActions.generated.txt | 50 +- .../Version0/Bind_T.generated.txt | 52 +- .../Bind_T_BinderOptions.generated.txt | 50 +- .../Version1/BindConfiguration.generated.txt | 36 +- ...gurationWithConfigureActions.generated.txt | 36 +- .../Version1/Bind_T.generated.txt | 36 +- .../Bind_T_BinderOptions.generated.txt | 36 +- .../Version0/Configure_T.generated.txt | 76 +-- .../Configure_T_BinderOptions.generated.txt | 76 +-- .../Version0/Configure_T_name.generated.txt | 76 +-- ...nfigure_T_name_BinderOptions.generated.txt | 76 +-- .../Version1/Configure_T.generated.txt | 66 +-- .../Configure_T_BinderOptions.generated.txt | 66 +-- .../Version1/Configure_T_name.generated.txt | 66 +-- ...nfigure_T_name_BinderOptions.generated.txt | 66 +-- .../Version0/Collections.generated.txt | 96 ++-- ...DefaultConstructorParameters.generated.txt | 188 ++++--- .../Version0/EmptyConfigType.generated.txt | 8 +- .../Version0/Primitives.generated.txt | 470 +++++++++++------ .../Version0/UnsupportedTypes.generated.txt | 69 +-- .../Version1/Collections.generated.txt | 84 +-- ...DefaultConstructorParameters.generated.txt | 138 +++-- .../Version1/Primitives.generated.txt | 462 ++++++++++------ .../Version1/UnsupportedTypes.generated.txt | 56 +- .../GeneratorTests.Helpers.cs | 2 +- 118 files changed, 5703 insertions(+), 3065 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs index b93489126c3984..e5ec446720e3dc 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs @@ -123,8 +123,15 @@ private void EmitGetCoreMethod() Identifier.value, Expression.sectionPath, writeOnSuccess: parsedValueExpr => _writer.WriteLine($"return {parsedValueExpr};"), - checkForNullSectionValue: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue); + checkForNullSectionValue: stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue, + Expression.errorOnFailedBinding); EmitEndBlock(); // End if-check for input type. + + if (stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue) + { + // The value is absent or could not be converted, and the caller did not ask for that to be an error. + _writer.WriteLine("return null;"); + } } break; case ConfigurationSectionSpec: @@ -198,7 +205,9 @@ private void EmitGetValueCoreMethod() Identifier.value, Expression.sectionPath, writeOnSuccess: (parsedValueExpr) => _writer.WriteLine($"return {parsedValueExpr};"), - checkForNullSectionValue: false); + checkForNullSectionValue: false, + // GetValue has no BinderOptions overload, so an unconvertible value is always an error. + errorOnFailedBindingExpr: "true"); EmitEndBlock(); } @@ -599,11 +608,17 @@ private void EmitEnumParseMethod() string parseEnumCall = _emitGenericParseEnum ? "Enum.Parse(value, ignoreCase: true)" : "(T)Enum.Parse(typeof(T), value, ignoreCase: true)"; _writer.WriteLine($$""" - public static T ParseEnum(string value, string? path) where T : struct + public static bool TryParseEnum(string {{Identifier.value}}, string? {{Identifier.path}}, bool {{Identifier.errorOnFailedBinding}}, out T {{Identifier.result}}) where T : struct { try { - return {{parseEnumCall}}; + {{Identifier.result}} = {{parseEnumCall}}; + return true; + } + catch when (!{{Identifier.errorOnFailedBinding}}) + { + {{Identifier.result}} = default; + return false; } catch ({{Identifier.Exception}} {{Identifier.exception}}) { @@ -667,11 +682,17 @@ private void EmitPrimitiveParseMethod(ParsableFromStringSpec type) string exceptionArg1 = string.Format(ExceptionMessages.FailedBinding, $"{{{Identifier.value} ?? \"null\"}}", $"{{{Identifier.path}}}", $"{{typeof({typeFQN})}}"); - EmitStartBlock($"public static {typeFQN} {TypeIndex.GetParseMethodName(type)}(string {Identifier.value}, string? {Identifier.path})"); + EmitStartBlock($"public static bool {TypeIndex.GetTryParseMethodName(type)}(string {Identifier.value}, string? {Identifier.path}, bool {Identifier.errorOnFailedBinding}, out {typeFQN} {Identifier.result})"); EmitEndBlock($$""" try { - return {{parsedValueExpr}}; + {{Identifier.result}} = {{parsedValueExpr}}; + return true; + } + catch when (!{{Identifier.errorOnFailedBinding}}) + { + {{Identifier.result}} = default; + return false; } catch ({{Identifier.Exception}} {{Identifier.exception}}) { @@ -724,7 +745,8 @@ private void EmitBindingLogicForEnumerableWithAdd(TypeRef elementTypeRef, string Identifier.value, Expression.sectionPath, (parsedValueExpr) => _writer.WriteLine($"{addExpr}({parsedValueExpr});"), - checkForNullSectionValue: true); + checkForNullSectionValue: true, + Expression.errorOnFailedBinding); EmitEndBlock(); // End if-check for input type. } break; @@ -777,7 +799,8 @@ private void EmitBindCoreImplForDictionary(DictionarySpec type) Expression.sectionKey, Expression.sectionPath, Emit_BindAndAddLogic_ForElement, - checkForNullSectionValue: false); + checkForNullSectionValue: false, + Expression.errorOnFailedBinding); void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr) { @@ -791,7 +814,8 @@ void Emit_BindAndAddLogic_ForElement(string parsedKeyExpr) Identifier.value, Expression.sectionPath, writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{instanceIdentifier}[{parsedKeyExpr}] = {parsedValueExpr};"), - checkForNullSectionValue: true); + checkForNullSectionValue: true, + Expression.errorOnFailedBinding); EmitEndBlock(); // End if-check for input type. } break; @@ -1000,15 +1024,34 @@ private bool EmitBindImplForMember( // A non-nullable value type parameter cannot take null: without a declared default // that falls through to the caller's else-branch, which throws; with one it keeps the - // default. An empty value still reaches the parse, which reports the conversion - // failure as the reflection binder does. + // default. An empty or otherwise unconvertible value is folded into the same condition + // so that it is treated the same way. bool requireValue = bindingToLocal && !member.TypeRef.CanBeNull && member is ParameterSpec; // A parameter's declared default has to survive a null value. bool hasDeclaredDefault = bindingToLocal && member is ParameterSpec { ErrorOnFailedBinding: false }; - string valueCondition = requireValue ? $" && {valueIdentifier} is not null" : string.Empty; - EmitStartBlock($"if ({Identifier.TryGetConfigurationValue}({Identifier.configuration}, {Identifier.key}: {SymbolDisplay.FormatLiteral(member.ConfigurationKeyName, quote: true)}, out string? {valueIdentifier}){valueCondition})"); + string configValueExpr = $"{Identifier.TryGetConfigurationValue}({Identifier.configuration}, {Identifier.key}: {SymbolDisplay.FormatLiteral(member.ConfigurationKeyName, quote: true)}, out string? {valueIdentifier})"; + + if (requireValue) + { + Debug.Assert(stringParsableType.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue); + + // Without a declared default the caller appends an else-branch that throws either + // way, so a value that is present but unconvertible reports the conversion failure + // rather than being described as missing configuration. + string errorOnFailedBindingExpr = hasDeclaredDefault ? Expression.errorOnFailedBinding : "true"; + + string tryParseExpr = GetTryParseExpression(stringParsableType, valueIdentifier, sectionPathExpr, errorOnFailedBindingExpr, out string parsedValueIdentifier); + + EmitStartBlock($"if ({configValueExpr} && {valueIdentifier} is not null && {tryParseExpr})"); + _writer.WriteLine($"{memberAccessExpr} = {parsedValueIdentifier};"); + EmitEndBlock(); + + return true; + } + + EmitStartBlock($"if ({configValueExpr})"); // Decide to emit the null check block for nullable types (e.g. int?). // We don't emit this block for types that can be assigned directly from IConfigurationSection.Value as the valueIdentifier value can assigned @@ -1040,7 +1083,8 @@ private bool EmitBindImplForMember( valueIdentifier, sectionPathExpr, writeOnSuccess: parsedValueExpr => _writer.WriteLine($"{memberAccessExpr} = {parsedValueExpr};"), - checkForNullSectionValue: !(emitNullCheck && treatEmptyValueAsNull) && !requireValue); + checkForNullSectionValue: !(emitNullCheck && treatEmptyValueAsNull), + Expression.errorOnFailedBinding); if (emitNullCheck) { @@ -1350,43 +1394,69 @@ private void EmitBindingLogic( string sectionValueExpr, string sectionPathExpr, Action? writeOnSuccess, - bool checkForNullSectionValue) + bool checkForNullSectionValue, + string errorOnFailedBindingExpr) { StringParsableTypeKind typeKind = type.StringParsableTypeKind; Debug.Assert(typeKind is not StringParsableTypeKind.None); - string parsedValueExpr = typeKind switch + // Usually assigning the configuration value to string or object. There is nothing to parse, so nothing can fail. + if (typeKind is StringParsableTypeKind.AssignFromSectionValue) { - StringParsableTypeKind.AssignFromSectionValue => sectionValueExpr, - StringParsableTypeKind.Enum => $"ParseEnum<{type.TypeRef.FullyQualifiedName}>({sectionValueExpr}, {sectionPathExpr})", - _ => $"{TypeIndex.GetParseMethodName(type)}({sectionValueExpr}, {sectionPathExpr})", - }; + writeOnSuccess?.Invoke(sectionValueExpr); + return; + } - // Usually assigning the configuration value to string or object - if (!checkForNullSectionValue || typeKind == StringParsableTypeKind.AssignFromSectionValue) + if (!checkForNullSectionValue) { - writeOnSuccess?.Invoke(parsedValueExpr); + EmitTryParseBlock(conditionPrefix: string.Empty, valueCondition: null); + return; } - else + + // Special case ByteArray when having empty string configuration value as we need to assign empty byte array at that time. + if (typeKind is StringParsableTypeKind.ByteArray) { - // call parsing methods + EmitTryParseBlock(conditionPrefix: string.Empty, valueCondition: $"{sectionValueExpr} == string.Empty"); + EmitTryParseBlock(conditionPrefix: "else ", valueCondition: $"!string.IsNullOrEmpty({sectionValueExpr})"); + return; + } - string conditionPrefix = string.Empty; - // Special case ByteArray when having empty string configuration value as we need to assign empty byte array at that time. - if (typeKind == StringParsableTypeKind.ByteArray) - { - EmitStartBlock($"if ({sectionValueExpr} == string.Empty)"); - writeOnSuccess?.Invoke(parsedValueExpr); - EmitEndBlock(); - conditionPrefix = "else "; - } + EmitTryParseBlock(conditionPrefix: string.Empty, valueCondition: $"!string.IsNullOrEmpty({sectionValueExpr})"); - EmitStartBlock($"{conditionPrefix}if (!string.IsNullOrEmpty({sectionValueExpr}))"); - writeOnSuccess?.Invoke(parsedValueExpr); + void EmitTryParseBlock(string conditionPrefix, string? valueCondition) + { + string tryParseExpr = GetTryParseExpression(type, sectionValueExpr, sectionPathExpr, errorOnFailedBindingExpr, out string parsedValueIdentifier); + string condition = valueCondition is null ? tryParseExpr : $"{valueCondition} && {tryParseExpr}"; + + EmitStartBlock($"{conditionPrefix}if ({condition})"); + writeOnSuccess?.Invoke(parsedValueIdentifier); EmitEndBlock(); } } + /// + /// Builds a call to the generated try-parse helper for , declaring the local that + /// receives the parsed value. A failed conversion only throws when the binder options ask for it, so the + /// caller emits its binding logic under the returned condition. + /// + private string GetTryParseExpression( + ParsableFromStringSpec type, + string sectionValueExpr, + string sectionPathExpr, + string errorOnFailedBindingExpr, + out string parsedValueIdentifier) + { + Debug.Assert(type.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue); + + string typeFQN = type.TypeRef.FullyQualifiedName; + string methodName = type.StringParsableTypeKind is StringParsableTypeKind.Enum + ? $"TryParseEnum<{typeFQN}>" + : TypeIndex.GetTryParseMethodName(type); + + parsedValueIdentifier = GetIncrementalIdentifier(Identifier.temp); + return $"{methodName}({sectionValueExpr}, {sectionPathExpr}, {errorOnFailedBindingExpr}, out {typeFQN} {parsedValueIdentifier})"; + } + private bool EmitObjectInit(ComplexTypeSpec type, string memberAccessExpr, InitializationKind initKind, string configArgExpr) { CollectionSpec? collectionType = type as CollectionSpec; diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/Helpers.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/Helpers.cs index a4f35ad3341e31..b5b9de538a4334 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/Helpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/Helpers.cs @@ -44,6 +44,7 @@ private enum ValueDefaulting private static class Expression { public const string configurationGetSection = "configuration.GetSection"; + public const string errorOnFailedBinding = $"{Identifier.binderOptions}?.{Identifier.ErrorOnUnknownConfiguration} is true"; public const string sectionKey = "section.Key"; public const string sectionPath = "section.Path"; public const string sectionValue = "section.Value"; @@ -72,6 +73,7 @@ private static class Identifier public const string defaultValue = nameof(defaultValue); public const string element = nameof(element); public const string enumValue = nameof(enumValue); + public const string errorOnFailedBinding = nameof(errorOnFailedBinding); public const string exception = nameof(exception); public const string key = nameof(key); public const string name = nameof(name); @@ -79,6 +81,7 @@ private static class Identifier public const string optionsBuilder = nameof(optionsBuilder); public const string originalCount = nameof(originalCount); public const string path = nameof(path); + public const string result = nameof(result); public const string section = nameof(section); public const string sectionKey = nameof(sectionKey); public const string services = nameof(services); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/TypeIndex.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/TypeIndex.cs index 029c6e848c7c1f..082d861237c8e9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/TypeIndex.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/TypeIndex.cs @@ -110,13 +110,13 @@ public bool KeyIsSupported(DictionarySpec typeSpec) => public static string GetConfigKeyCacheFieldName(ObjectSpec type) => $"s_configKeys_{type.IdentifierCompatibleSubstring}"; - public static string GetParseMethodName(ParsableFromStringSpec type) + public static string GetTryParseMethodName(ParsableFromStringSpec type) { Debug.Assert(type.StringParsableTypeKind is not StringParsableTypeKind.AssignFromSectionValue); if (type.StringParsableTypeKind is StringParsableTypeKind.ByteArray) { - return "ParseByteArray"; + return "TryParseByteArray"; } string displayString = type.TypeRef.FullyQualifiedName; @@ -138,7 +138,7 @@ public static string GetParseMethodName(ParsableFromStringSpec type) displayString = displayString.Replace(".", ""); } - return "Parse" + displayString; + return "TryParse" + displayString; } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index d659b25f73ffe7..15b0f1bb98c4b6 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -327,7 +327,8 @@ private static void BindInstance( BindingPoint bindingPoint, IConfiguration config, BinderOptions options, - bool isParentCollection) + bool isParentCollection, + bool errorOnFailedBinding = false) { // if binding IConfigurationSection, break early if (type == typeof(IConfigurationSection)) @@ -361,7 +362,15 @@ private static void BindInstance( { if (error != null) { - throw error; + // A conversion failure is only reported when the caller opted in, matching how the binder treats + // a leaf value it has no converter for at all. Otherwise the binding point is left alone so the + // member keeps whatever value it already had. + if (options.ErrorOnUnknownConfiguration || errorOnFailedBinding) + { + throw error; + } + + return; } if (type == typeof(byte[]) && bindingPoint.Value is byte[] byteArray && byteArray.Length > 0) @@ -1153,24 +1162,41 @@ private static List GetAllProperties( var propertyBindingPoint = new BindingPoint(isReadOnly: false); + bool canBeNull = CanBeNull(parameter.ParameterType); + bool hasDefaultValue = false; + object? defaultValue = null; + + // A parameter that can hold null is always satisfiable, so its default is only needed on the failure + // path. For the rest, knowing up front whether a default exists decides whether a value that is present + // but unconvertible should surface as a conversion error instead of being reported as missing. + if (!canBeNull) + { + hasDefaultValue = ParameterDefaultValue.TryGetDefaultValue(parameter, out defaultValue); + } + BindInstance( parameter.ParameterType, propertyBindingPoint, config.GetSection(parameterName), options, - false); + false, + errorOnFailedBinding: !canBeNull && !hasDefaultValue); if (propertyBindingPoint.Value is null) { - if (ParameterDefaultValue.TryGetDefaultValue(parameter, out object? defaultValue)) + if (canBeNull) { - return defaultValue; + return ParameterDefaultValue.TryGetDefaultValue(parameter, out object? nullableDefaultValue) + ? nullableDefaultValue + : null; } - if (!CanBeNull(parameter.ParameterType)) + if (!hasDefaultValue) { throw new InvalidOperationException(SR.Format(SR.Error_ParameterHasNoMatchingConfig, type, parameterName)); } + + return defaultValue; } return propertyBindingPoint.Value; diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs index 7274a8d55a47a4..75bbeddaef2875 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs @@ -511,6 +511,11 @@ public class ByteArrayOptions public byte[] MyByteArray { get; set; } } + public class OptionsWithPresetIntegerValue + { + public int IntegerValue { get; set; } = 11; + } + public enum TestSettingsEnum { Option1, @@ -529,7 +534,7 @@ public class MyModelContainingADictionary public Dictionary Enums { get; set; } } - [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] // Ensure exception messages are in sync + [Fact] public void WithFlagUnset_NoExceptionIsThrownWhenFailingToParseEnumsInAnArrayAndValidItemsArePreserved() { var dic = new Dictionary @@ -552,7 +557,7 @@ public void WithFlagUnset_NoExceptionIsThrownWhenFailingToParseEnumsInAnArrayAnd Assert.Equal(TestSettingsEnum.Option2, model.Enums[1]); } - [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] // Ensure exception messages are in sync + [Fact] public void WithFlagUnset_NoExceptionIsThrownWhenFailingToParseEnumsInADictionaryAndValidItemsArePreserved() { var dic = new Dictionary diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs index 31fc33321e102b..c2ec4d2e40d949 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs @@ -710,13 +710,13 @@ public void ConsistentExceptionOnFailedBinding(Type type) // act #pragma warning disable SYSLIB1104 var exception = Assert.Throws( - () => config.Bind(options)); + () => config.Bind(options, o => o.ErrorOnUnknownConfiguration = true)); var getValueException = Assert.Throws( () => config.GetValue(type, "Value")); var getException = Assert.Throws( - () => config.GetSection("Value").Get(type)); + () => config.GetSection("Value").Get(type, o => o.ErrorOnUnknownConfiguration = true)); #pragma warning restore SYSLIB1104 // assert @@ -751,7 +751,7 @@ public void ExceptionOnFailedBindingIncludesPath() var options = new OptionsWithNesting(); var exception = Assert.Throws( - () => config.Bind(options)); + () => config.Bind(options, o => o.ErrorOnUnknownConfiguration = true)); Assert.Equal(SR.Format(SR.Error_FailedBinding, IncorrectValue, ConfigKey, typeof(int)), exception.Message); @@ -1161,7 +1161,8 @@ public void ExceptionWhenConstructorParameterCannotBeNullAndConfigurationValueIs { if (hasDefaultValue) { - config.Get(); + // A declared default absorbs the unconvertible value unless the caller opts into errors. + config.Get(o => o.ErrorOnUnknownConfiguration = true); } else { @@ -1174,6 +1175,14 @@ public void ExceptionWhenConstructorParameterCannotBeNullAndConfigurationValueIs exception.Message); } + [Fact] + public void ConstructorParameterUsesItsDefaultValueWhenConfigurationValueCannotBeConverted() + { + IConfiguration config = TestHelpers.GetConfigurationFromJsonString("""{ "Value": "" }"""); + + Assert.Equal(42, config.Get().Value); + } + [Theory] [InlineData("""{ "Value": null }""")] [InlineData("""{ "Unrelated": "value" }""")] @@ -2300,7 +2309,7 @@ public void ExceptionWhenTryingToBindToByteArray() configurationBuilder.AddInMemoryCollection(dic); var config = configurationBuilder.Build(); - var exception = Assert.Throws(() => config.Get()); + var exception = Assert.Throws(() => config.Get(o => o.ErrorOnUnknownConfiguration = true)); Assert.Equal( SR.Format(SR.Error_FailedBinding, "(not a valid base64 string)", "MyByteArray", typeof(byte[])), exception.Message); @@ -3437,6 +3446,40 @@ public void EnsureThrowingWithCollectionAndErrorOnUnknownConfigurationOption() internal class TestSettings { public Dictionary Values { get; init; } = []; } #endif + [Theory] + [InlineData("""{ "IntegerValue": "" }""")] + [InlineData("""{ "IntegerValue": "not-an-integer" }""")] + public void UnconvertibleValueLeavesMemberAloneWhenErrorOnUnknownConfigurationIsNotSet(string json) + { + IConfiguration config = TestHelpers.GetConfigurationFromJsonString(json); + + Assert.Equal(11, config.Get().IntegerValue); + + OptionsWithPresetIntegerValue instance = new() { IntegerValue = 7 }; + config.Bind(instance); + Assert.Equal(7, instance.IntegerValue); + } + + [Fact] + public void UnconvertibleValueThrowsWhenErrorOnUnknownConfigurationIsSet() + { + IConfiguration config = TestHelpers.GetConfigurationFromJsonString("""{ "IntegerValue": "not-an-integer" }"""); + + Assert.Throws( + () => config.Get(o => o.ErrorOnUnknownConfiguration = true)); + + Assert.Throws( + () => config.Bind(new OptionsWithPresetIntegerValue(), o => o.ErrorOnUnknownConfiguration = true)); + } + + [Fact] + public void GetValueStillThrowsOnUnconvertibleValue() + { + IConfiguration config = TestHelpers.GetConfigurationFromJsonString("""{ "IntegerValue": "not-an-integer" }"""); + + Assert.Throws(() => config.GetValue("IntegerValue")); + } + [Fact] public void BindWithNullValues() { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind.generated.txt index 600f031efe4a16..c087c9c24c6c5c 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind.generated.txt @@ -36,7 +36,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #region IConfiguration extensions. /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively. [InterceptsLocation(@"src-0.cs", 12, 14)] - public static void Bind_ProgramMyClass(this IConfiguration configuration, object? instance) + public static void Bind_Program__MyClass(this IConfiguration configuration, object? instance) { if (configuration is null) { @@ -54,7 +54,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively. [InterceptsLocation(@"src-0.cs", 13, 20)] - public static void Bind_ProgramMyClass(this IConfiguration configuration, object? instance, Action? configureOptions) + public static void Bind_Program__MyClass(this IConfiguration configuration, object? instance, Action? configureOptions) { if (configuration is null) { @@ -72,7 +72,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively. [InterceptsLocation(@"src-0.cs", 14, 20)] - public static void Bind_ProgramMyClass(this IConfiguration configuration, string key, object? instance) + public static void Bind_Program__MyClass(this IConfiguration configuration, string key, object? instance) { if (configuration is null) { @@ -90,15 +90,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) + { + instance.Add(temp0); + } } } } @@ -107,7 +110,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance[section.Key] = value; } @@ -128,11 +131,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value0) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -143,53 +146,83 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) + { + instance.MyInt = temp3; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section2) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) + { + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; + } + else { - global::System.Collections.Generic.List? temp4 = instance.MyList; - temp4 ??= new global::System.Collections.Generic.List(); - BindCore(section2, ref temp4, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp4; + instance.MyList = instance.MyList; } - if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section5) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp7 = instance.MyDictionary; - temp7 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp7; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; + } + else + { + instance.MyDictionary = instance.MyDictionary; } - if (AsConfigWithChildren(configuration.GetSection("MyComplexDictionary")) is IConfigurationSection section8) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp10 = instance.MyComplexDictionary; - temp10 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp10; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } + else + { + instance.MyComplexDictionary = instance.MyComplexDictionary; + } + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -227,15 +260,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Instance.generated.txt index ed5a0bb6041221..902fa4a4b55129 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Instance.generated.txt @@ -36,7 +36,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #region IConfiguration extensions. /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively. [InterceptsLocation(@"src-0.cs", 12, 20)] - public static void Bind_ProgramMyClass(this IConfiguration configuration, object? instance) + public static void Bind_Program__MyClass(this IConfiguration configuration, object? instance) { if (configuration is null) { @@ -54,15 +54,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) + { + instance.Add(temp0); + } } } } @@ -71,7 +74,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance[section.Key] = value; } @@ -92,11 +95,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value0) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -107,53 +110,83 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) + { + instance.MyInt = temp3; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section2) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) + { + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; + } + else { - global::System.Collections.Generic.List? temp4 = instance.MyList; - temp4 ??= new global::System.Collections.Generic.List(); - BindCore(section2, ref temp4, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp4; + instance.MyList = instance.MyList; } - if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section5) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp7 = instance.MyDictionary; - temp7 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp7; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; + } + else + { + instance.MyDictionary = instance.MyDictionary; } - if (AsConfigWithChildren(configuration.GetSection("MyComplexDictionary")) is IConfigurationSection section8) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp10 = instance.MyComplexDictionary; - temp10 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp10; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } + else + { + instance.MyComplexDictionary = instance.MyComplexDictionary; + } + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -173,15 +206,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Instance_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Instance_BinderOptions.generated.txt index 78fe9de943c24d..84d50ae264ecc5 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Instance_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Instance_BinderOptions.generated.txt @@ -36,7 +36,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #region IConfiguration extensions. /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively. [InterceptsLocation(@"src-0.cs", 12, 20)] - public static void Bind_ProgramMyClass(this IConfiguration configuration, object? instance, Action? configureOptions) + public static void Bind_Program__MyClass(this IConfiguration configuration, object? instance, Action? configureOptions) { if (configuration is null) { @@ -54,15 +54,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) + { + instance.Add(temp0); + } } } } @@ -71,7 +74,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance[section.Key] = value; } @@ -92,11 +95,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value0) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -107,53 +110,83 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) + { + instance.MyInt = temp3; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section2) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) + { + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; + } + else { - global::System.Collections.Generic.List? temp4 = instance.MyList; - temp4 ??= new global::System.Collections.Generic.List(); - BindCore(section2, ref temp4, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp4; + instance.MyList = instance.MyList; } - if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section5) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp7 = instance.MyDictionary; - temp7 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp7; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; + } + else + { + instance.MyDictionary = instance.MyDictionary; } - if (AsConfigWithChildren(configuration.GetSection("MyComplexDictionary")) is IConfigurationSection section8) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp10 = instance.MyComplexDictionary; - temp10 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp10; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } + else + { + instance.MyComplexDictionary = instance.MyComplexDictionary; + } + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -191,15 +224,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Key_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Key_Instance.generated.txt index 0ee5e6704c859c..5ce9bd454c70d7 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Key_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_Key_Instance.generated.txt @@ -36,7 +36,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #region IConfiguration extensions. /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively. [InterceptsLocation(@"src-0.cs", 12, 20)] - public static void Bind_ProgramMyClass(this IConfiguration configuration, string key, object? instance) + public static void Bind_Program__MyClass(this IConfiguration configuration, string key, object? instance) { if (configuration is null) { @@ -54,15 +54,18 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) + { + instance.Add(temp0); + } } } } @@ -71,7 +74,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance[section.Key] = value; } @@ -92,11 +95,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value0) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -107,53 +110,83 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) + { + instance.MyInt = temp3; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section2) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) + { + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; + } + else { - global::System.Collections.Generic.List? temp4 = instance.MyList; - temp4 ??= new global::System.Collections.Generic.List(); - BindCore(section2, ref temp4, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp4; + instance.MyList = instance.MyList; } - if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section5) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp7 = instance.MyDictionary; - temp7 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp7; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; + } + else + { + instance.MyDictionary = instance.MyDictionary; } - if (AsConfigWithChildren(configuration.GetSection("MyComplexDictionary")) is IConfigurationSection section8) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp10 = instance.MyComplexDictionary; - temp10 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp10; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } + else + { + instance.MyComplexDictionary = instance.MyComplexDictionary; + } + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -173,15 +206,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_ParseTypeFromMethodParam.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_ParseTypeFromMethodParam.generated.txt index 2a1453546c7bf9..dd8f6cf3c336be 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_ParseTypeFromMethodParam.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Bind_ParseTypeFromMethodParam.generated.txt @@ -36,24 +36,36 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #region IConfiguration extensions. /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively. [InterceptsLocation(@"src-0.cs", 18, 16)] - public static void Bind_ProgramMyClass0(this IConfiguration configuration, object? instance) + public static void Bind_Program__MyClass0(this IConfiguration configuration, object? instance) { } /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively. [InterceptsLocation(@"src-0.cs", 23, 16)] - public static void Bind_ProgramMyClass1(this IConfiguration configuration, object? instance, Action? configureOptions) + public static void Bind_Program__MyClass1(this IConfiguration configuration, object? instance, Action? configureOptions) { } /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively. [InterceptsLocation(@"src-0.cs", 28, 16)] - public static void Bind_ProgramMyClass2(this IConfiguration configuration, string key, object? instance) + public static void Bind_Program__MyClass2(this IConfiguration configuration, string key, object? instance) { } #endregion IConfiguration extensions. #region Core binding extensions. + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + public static BinderOptions? GetBinderOptions(Action? configureOptions) { if (configureOptions is null) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get.generated.txt index f6c9df459af26c..92aa881a361141 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get.generated.txt @@ -52,8 +52,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); - private readonly static Lazy> s_configKeys_ProgramMyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -89,35 +89,41 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) + { + instance.Add(temp2); + } } } } public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp2 = new List(); + var temp3 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - temp2.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) + { + temp3.Add(temp4); + } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp2.Count); - temp2.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp3.Count); + temp3.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance[section.Key] = value; } @@ -126,11 +132,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value3) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -141,47 +147,72 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value4) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) + { + instance.MyInt = temp7; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section5) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp7 = instance.MyList; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp7; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; + } + else + { + instance.MyList = instance.MyList; } - if (AsConfigWithChildren(configuration.GetSection("MyArray")) is IConfigurationSection section8) + var value12 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) + { + int[]? temp15 = instance.MyArray; + temp15 ??= new int[0]; + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp15; + } + else { - int[]? temp10 = instance.MyArray; - temp10 ??= new int[0]; - BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp10; + instance.MyArray = instance.MyArray; + } + if (instance.MyArray is null && TryGetConfigurationValue(value12, key: null, out string? value16) && value16 == string.Empty) + { + instance.MyArray = global::System.Array.Empty(); } - if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section11) + var value17 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value17) is IConfigurationSection section18) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp20 = instance.MyDictionary; + temp20 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section18, ref temp20, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp20; + } + else + { + instance.MyDictionary = instance.MyDictionary; } } public static void BindCore(IConfiguration configuration, ref global::Program.MyClass2 instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (configuration["MyInt"] is string value14) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value21)) { - instance.MyInt = ParseInt(value14, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value21) && TryParseInt(value21, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp22)) + { + instance.MyInt = temp22; + } } else if (defaultValueIfNotFound) { @@ -189,19 +220,31 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -248,15 +291,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue.generated.txt index 7466c543a85e53..a82e4c2313c7fc 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue.generated.txt @@ -60,76 +60,122 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration IConfigurationSection section = configuration.GetSection(key); - if (section.Value is not string value) + if (TryGetConfigurationValue(section, key: null, out string? value) && !string.IsNullOrEmpty(value)) { - return null; + if (type == typeof(int)) + { + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } + } + else if (type == typeof(bool?)) + { + if (TryParseBool(value, section.Path, true, out bool temp1)) + { + return temp1; + } + } + else if (type == typeof(byte[])) + { + if (TryParseByteArray(value, section.Path, true, out byte[] temp2)) + { + return temp2; + } + } + else if (type == typeof(global::System.Globalization.CultureInfo)) + { + if (TryParseSystemGlobalizationCultureInfo(value, section.Path, true, out global::System.Globalization.CultureInfo temp3)) + { + return temp3; + } + } } - if (type == typeof(int)) - { - return ParseInt(value, section.Path); - } - else if (type == typeof(bool?)) - { - return ParseBool(value, section.Path); - } - else if (type == typeof(byte[])) - { - return ParseByteArray(value, section.Path); - } - else if (type == typeof(global::System.Globalization.CultureInfo)) + return null; + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) { - return ParseSystemGlobalizationCultureInfo(value, section.Path); + return section.TryGetValue(key, out value); } - - return null; + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(bool)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(bool)}'.", exception); } } - public static byte[] ParseByteArray(string value, string? path) + public static bool TryParseByteArray(string value, string? path, bool errorOnFailedBinding, out byte[] result) { try { - return Convert.FromBase64String(value); + result = Convert.FromBase64String(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(byte[])}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(byte[])}'.", exception); } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_T_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_T_Key.generated.txt index 4f822c0f75d64b..2129071b2866fa 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_T_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_T_Key.generated.txt @@ -48,28 +48,47 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration IConfigurationSection section = configuration.GetSection(key); - if (section.Value is not string value) + if (TryGetConfigurationValue(section, key: null, out string? value) && !string.IsNullOrEmpty(value)) { - return null; + if (type == typeof(int)) + { + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } + } } - if (type == typeof(int)) + return null; + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) { - return ParseInt(value, section.Path); + return section.TryGetValue(key, out value); } - - return null; + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_T_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_T_Key_DefaultValue.generated.txt index f7fe233d3569ce..d1bc04448aa644 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_T_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_T_Key_DefaultValue.generated.txt @@ -48,28 +48,47 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration IConfigurationSection section = configuration.GetSection(key); - if (section.Value is not string value) + if (TryGetConfigurationValue(section, key: null, out string? value) && !string.IsNullOrEmpty(value)) { - return null; + if (type == typeof(int)) + { + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } + } } - if (type == typeof(int)) + return null; + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) { - return ParseInt(value, section.Path); + return section.TryGetValue(key, out value); } - - return null; + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_TypeOf_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_TypeOf_Key.generated.txt index 644f3ce18e82f4..e5dce4222dd927 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_TypeOf_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_TypeOf_Key.generated.txt @@ -48,28 +48,47 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration IConfigurationSection section = configuration.GetSection(key); - if (section.Value is not string value) + if (TryGetConfigurationValue(section, key: null, out string? value) && !string.IsNullOrEmpty(value)) { - return null; + if (type == typeof(bool?)) + { + if (TryParseBool(value, section.Path, true, out bool temp0)) + { + return temp0; + } + } } - if (type == typeof(bool?)) + return null; + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) { - return ParseBool(value, section.Path); + return section.TryGetValue(key, out value); } - - return null; + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(bool)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(bool)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_TypeOf_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_TypeOf_Key_DefaultValue.generated.txt index ebf24068b77fa7..7a49224e6fb322 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_TypeOf_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/GetValue_TypeOf_Key_DefaultValue.generated.txt @@ -48,28 +48,47 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration IConfigurationSection section = configuration.GetSection(key); - if (section.Value is not string value) + if (TryGetConfigurationValue(section, key: null, out string? value) && !string.IsNullOrEmpty(value)) { - return null; + if (type == typeof(global::System.Globalization.CultureInfo)) + { + if (TryParseSystemGlobalizationCultureInfo(value, section.Path, true, out global::System.Globalization.CultureInfo temp0)) + { + return temp0; + } + } } - if (type == typeof(global::System.Globalization.CultureInfo)) + return null; + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) { - return ParseSystemGlobalizationCultureInfo(value, section.Path); + return section.TryGetValue(key, out value); } - - return null; + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_PrimitivesOnly.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_PrimitivesOnly.generated.txt index 29d5a787ef3be2..0e3f052ed4fb5f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_PrimitivesOnly.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_PrimitivesOnly.generated.txt @@ -71,10 +71,14 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { throw new InvalidOperationException(); } - if (section.Value is string value) + if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - return ParseInt(value, section.Path); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) + { + return temp0; + } } + return null; } else if (type == typeof(string)) { @@ -82,7 +86,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { throw new InvalidOperationException(); } - return section.Value; + if (TryGetConfigurationValue(configuration, key: null, out string? value)) + { + return value; + } } else if (type == typeof(float)) { @@ -90,10 +97,14 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { throw new InvalidOperationException(); } - if (section.Value is string value) + if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - return ParseFloat(value, section.Path); + if (!string.IsNullOrEmpty(value) && TryParseFloat(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp1)) + { + return temp1; + } } + return null; } else if (type == typeof(double)) { @@ -101,15 +112,31 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { throw new InvalidOperationException(); } - if (section.Value is string value) + if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - return ParseDouble(value, section.Path); + if (!string.IsNullOrEmpty(value) && TryParseDouble(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp2)) + { + return temp2; + } } + return null; } throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input."); } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + public static bool HasValueOrChildren(IConfiguration configuration) { if ((configuration as IConfigurationSection)?.Value is not null) @@ -146,39 +173,57 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(float)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(float)}'.", exception); } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(double)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(double)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_T.generated.txt index fd3c9297004774..887fe270597b75 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_T.generated.txt @@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -70,35 +70,41 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) + { + instance.Add(temp1); + } } } } public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp1 = new List(); + var temp2 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - temp1.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) + { + temp2.Add(temp3); + } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp1.Count); - temp1.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp2.Count); + temp2.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance[section.Key] = value; } @@ -107,11 +113,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value2) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value4)) { - instance.MyString = value2; + instance.MyString = value4; } else if (defaultValueIfNotFound) { @@ -122,53 +128,87 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value3) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value5)) { - instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value5) && TryParseInt(value5, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp6)) + { + instance.MyInt = temp6; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section4) + var value7 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value7) is IConfigurationSection section8) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp10 = instance.MyList; + temp10 ??= new global::System.Collections.Generic.List(); + BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp10; + } + else + { + instance.MyList = instance.MyList; } - if (AsConfigWithChildren(configuration.GetSection("MyArray")) is IConfigurationSection section7) + var value11 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value11) is IConfigurationSection section12) + { + int[]? temp14 = instance.MyArray; + temp14 ??= new int[0]; + BindCore(section12, ref temp14, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp14; + } + else + { + instance.MyArray = instance.MyArray; + } + if (instance.MyArray is null && TryGetConfigurationValue(value11, key: null, out string? value15) && value15 == string.Empty) { - int[]? temp9 = instance.MyArray; - temp9 ??= new int[0]; - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp9; + instance.MyArray = global::System.Array.Empty(); } - if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section10) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp12 = instance.MyDictionary; - temp12 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp12; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; + } + else + { + instance.MyDictionary = instance.MyDictionary; } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -215,15 +255,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_T_BinderOptions.generated.txt index 201d628018b3cb..4bf1a1c94d3d10 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_T_BinderOptions.generated.txt @@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -70,35 +70,41 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) + { + instance.Add(temp1); + } } } } public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp1 = new List(); + var temp2 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - temp1.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) + { + temp2.Add(temp3); + } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp1.Count); - temp1.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp2.Count); + temp2.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance[section.Key] = value; } @@ -107,11 +113,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value2) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value4)) { - instance.MyString = value2; + instance.MyString = value4; } else if (defaultValueIfNotFound) { @@ -122,53 +128,87 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value3) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value5)) { - instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value5) && TryParseInt(value5, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp6)) + { + instance.MyInt = temp6; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section4) + var value7 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value7) is IConfigurationSection section8) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp10 = instance.MyList; + temp10 ??= new global::System.Collections.Generic.List(); + BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp10; + } + else + { + instance.MyList = instance.MyList; } - if (AsConfigWithChildren(configuration.GetSection("MyArray")) is IConfigurationSection section7) + var value11 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value11) is IConfigurationSection section12) + { + int[]? temp14 = instance.MyArray; + temp14 ??= new int[0]; + BindCore(section12, ref temp14, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp14; + } + else + { + instance.MyArray = instance.MyArray; + } + if (instance.MyArray is null && TryGetConfigurationValue(value11, key: null, out string? value15) && value15 == string.Empty) { - int[]? temp9 = instance.MyArray; - temp9 ??= new int[0]; - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp9; + instance.MyArray = global::System.Array.Empty(); } - if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section10) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp12 = instance.MyDictionary; - temp12 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp12; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; + } + else + { + instance.MyDictionary = instance.MyDictionary; } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -215,15 +255,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_TypeOf.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_TypeOf.generated.txt index b5a93a34f7fe3e..eba2a1dbbcc35c 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_TypeOf.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_TypeOf.generated.txt @@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -68,11 +68,14 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass2 instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (configuration["MyInt"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value1) && TryParseInt(value1, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) + { + instance.MyInt = temp2; + } } else if (defaultValueIfNotFound) { @@ -80,19 +83,31 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -139,15 +154,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_TypeOf_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_TypeOf_BinderOptions.generated.txt index b908df33810cd0..7e98feefdc7454 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_TypeOf_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version0/Get_TypeOf_BinderOptions.generated.txt @@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -68,11 +68,14 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass2 instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (configuration["MyInt"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value1) && TryParseInt(value1, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) + { + instance.MyInt = temp2; + } } else if (defaultValueIfNotFound) { @@ -80,19 +83,31 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -139,15 +154,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind.generated.txt index c86526984b3d40..f6c93601711db0 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind.generated.txt @@ -98,9 +98,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -133,9 +133,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -146,11 +146,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -158,39 +158,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -260,11 +260,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Instance.generated.txt index 5bc1ad637bd7b5..31166b1bffb834 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Instance.generated.txt @@ -62,9 +62,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -97,9 +97,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -110,11 +110,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -122,39 +122,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -206,11 +206,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Instance_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Instance_BinderOptions.generated.txt index c6c7feafc3cd66..524e30a62f0b8a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Instance_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Instance_BinderOptions.generated.txt @@ -62,9 +62,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -97,9 +97,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -110,11 +110,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -122,39 +122,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -224,11 +224,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Key_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Key_Instance.generated.txt index 27ada27eeb2f74..a08d850ec59f58 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Key_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Bind_Key_Instance.generated.txt @@ -62,9 +62,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -97,9 +97,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -110,11 +110,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -122,39 +122,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -206,11 +206,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get.generated.txt index 07b5468ceea345..e1719bba0d467f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get.generated.txt @@ -91,9 +91,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp2); } } } @@ -101,22 +101,22 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp2 = new List(); + var temp3 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - temp2.Add(ParseInt(value, section.Path)); + temp3.Add(temp4); } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp2.Count); - temp2.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp3.Count); + temp3.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) @@ -134,9 +134,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -147,11 +147,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -159,43 +159,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyArray"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - int[]? temp12 = instance.MyArray; - temp12 ??= new int[0]; - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp12; + int[]? temp15 = instance.MyArray; + temp15 ??= new int[0]; + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp15; } else { instance.MyArray = instance.MyArray; } - if (instance.MyArray is null && TryGetConfigurationValue(value9, key: null, out string? value13) && value13 == string.Empty) + if (instance.MyArray is null && TryGetConfigurationValue(value12, key: null, out string? value16) && value16 == string.Empty) { instance.MyArray = global::System.Array.Empty(); } - var value14 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value14) is IConfigurationSection section15) + var value17 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value17) is IConfigurationSection section18) { - global::System.Collections.Generic.Dictionary? temp17 = instance.MyDictionary; - temp17 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section15, ref temp17, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp17; + global::System.Collections.Generic.Dictionary? temp20 = instance.MyDictionary; + temp20 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section18, ref temp20, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp20; } else { @@ -207,11 +207,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value18)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value21)) { - if (!string.IsNullOrEmpty(value18)) + if (!string.IsNullOrEmpty(value21) && TryParseInt(value21, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp22)) { - instance.MyInt = ParseInt(value18, configuration.GetSection("MyInt").Path); + instance.MyInt = temp22; } } else if (defaultValueIfNotFound) @@ -291,11 +291,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue.generated.txt index ad3f7ab95c9472..7d7c08fceb1ceb 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue.generated.txt @@ -64,19 +64,31 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(int)) { - return ParseInt(value, section.Path); + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } } else if (type == typeof(bool?)) { - return ParseBool(value, section.Path); + if (TryParseBool(value, section.Path, true, out bool temp1)) + { + return temp1; + } } else if (type == typeof(byte[])) { - return ParseByteArray(value, section.Path); + if (TryParseByteArray(value, section.Path, true, out byte[] temp2)) + { + return temp2; + } } else if (type == typeof(global::System.Globalization.CultureInfo)) { - return ParseSystemGlobalizationCultureInfo(value, section.Path); + if (TryParseSystemGlobalizationCultureInfo(value, section.Path, true, out global::System.Globalization.CultureInfo temp3)) + { + return temp3; + } } } @@ -95,11 +107,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -107,11 +125,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -119,11 +143,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static byte[] ParseByteArray(string value, string? path) + public static bool TryParseByteArray(string value, string? path, bool errorOnFailedBinding, out byte[] result) { try { - return Convert.FromBase64String(value); + result = Convert.FromBase64String(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -131,11 +161,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_T_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_T_Key.generated.txt index cd9549063e3b8e..4dbd3edbea4428 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_T_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_T_Key.generated.txt @@ -52,7 +52,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(int)) { - return ParseInt(value, section.Path); + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } } } @@ -71,11 +74,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_T_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_T_Key_DefaultValue.generated.txt index d5830fd0832b44..53b1d429461ac3 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_T_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_T_Key_DefaultValue.generated.txt @@ -52,7 +52,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(int)) { - return ParseInt(value, section.Path); + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } } } @@ -71,11 +74,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_TypeOf_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_TypeOf_Key.generated.txt index 975269f002e347..934f6ea4fda083 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_TypeOf_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_TypeOf_Key.generated.txt @@ -52,7 +52,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(bool?)) { - return ParseBool(value, section.Path); + if (TryParseBool(value, section.Path, true, out bool temp0)) + { + return temp0; + } } } @@ -71,11 +74,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_TypeOf_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_TypeOf_Key_DefaultValue.generated.txt index b3f7dd1eefb627..92fc0ffce0536a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_TypeOf_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/GetValue_TypeOf_Key_DefaultValue.generated.txt @@ -52,7 +52,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(global::System.Globalization.CultureInfo)) { - return ParseSystemGlobalizationCultureInfo(value, section.Path); + if (TryParseSystemGlobalizationCultureInfo(value, section.Path, true, out global::System.Globalization.CultureInfo temp0)) + { + return temp0; + } } } @@ -71,11 +74,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_PrimitivesOnly.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_PrimitivesOnly.generated.txt index 2d4f4da184a350..0521edc9fb4e2f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_PrimitivesOnly.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_PrimitivesOnly.generated.txt @@ -73,11 +73,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - return ParseInt(value, section.Path); + return temp0; } } + return null; } else if (type == typeof(string)) { @@ -98,11 +99,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseFloat(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp1)) { - return ParseFloat(value, section.Path); + return temp1; } } + return null; } else if (type == typeof(double)) { @@ -112,11 +114,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseDouble(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp2)) { - return ParseDouble(value, section.Path); + return temp2; } } + return null; } throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input."); @@ -170,11 +173,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -182,11 +191,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -194,11 +209,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_T.generated.txt index 2067a714833529..76fdadbfffb4c9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_T.generated.txt @@ -72,9 +72,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -82,22 +82,22 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp1 = new List(); + var temp2 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - temp1.Add(ParseInt(value, section.Path)); + temp2.Add(temp3); } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp1.Count); - temp1.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp2.Count); + temp2.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) @@ -115,9 +115,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value4)) { - instance.MyString = value2; + instance.MyString = value4; } else if (defaultValueIfNotFound) { @@ -128,11 +128,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value5)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value5) && TryParseInt(value5, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp6)) { - instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); + instance.MyInt = temp6; } } else if (defaultValueIfNotFound) @@ -140,43 +140,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value4 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value4) is IConfigurationSection section5) + var value7 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value7) is IConfigurationSection section8) { - global::System.Collections.Generic.List? temp7 = instance.MyList; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp7; + global::System.Collections.Generic.List? temp10 = instance.MyList; + temp10 ??= new global::System.Collections.Generic.List(); + BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp10; } else { instance.MyList = instance.MyList; } - var value8 = configuration.GetSection("MyArray"); - if (AsConfigWithChildren(value8) is IConfigurationSection section9) + var value11 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value11) is IConfigurationSection section12) { - int[]? temp11 = instance.MyArray; - temp11 ??= new int[0]; - BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp11; + int[]? temp14 = instance.MyArray; + temp14 ??= new int[0]; + BindCore(section12, ref temp14, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp14; } else { instance.MyArray = instance.MyArray; } - if (instance.MyArray is null && TryGetConfigurationValue(value8, key: null, out string? value12) && value12 == string.Empty) + if (instance.MyArray is null && TryGetConfigurationValue(value11, key: null, out string? value15) && value15 == string.Empty) { instance.MyArray = global::System.Array.Empty(); } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -255,11 +255,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_T_BinderOptions.generated.txt index 7f443cb8ec7c26..02df56d40634a3 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_T_BinderOptions.generated.txt @@ -72,9 +72,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -82,22 +82,22 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp1 = new List(); + var temp2 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - temp1.Add(ParseInt(value, section.Path)); + temp2.Add(temp3); } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp1.Count); - temp1.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp2.Count); + temp2.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) @@ -115,9 +115,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value4)) { - instance.MyString = value2; + instance.MyString = value4; } else if (defaultValueIfNotFound) { @@ -128,11 +128,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value5)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value5) && TryParseInt(value5, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp6)) { - instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); + instance.MyInt = temp6; } } else if (defaultValueIfNotFound) @@ -140,43 +140,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value4 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value4) is IConfigurationSection section5) + var value7 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value7) is IConfigurationSection section8) { - global::System.Collections.Generic.List? temp7 = instance.MyList; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp7; + global::System.Collections.Generic.List? temp10 = instance.MyList; + temp10 ??= new global::System.Collections.Generic.List(); + BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp10; } else { instance.MyList = instance.MyList; } - var value8 = configuration.GetSection("MyArray"); - if (AsConfigWithChildren(value8) is IConfigurationSection section9) + var value11 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value11) is IConfigurationSection section12) { - int[]? temp11 = instance.MyArray; - temp11 ??= new int[0]; - BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp11; + int[]? temp14 = instance.MyArray; + temp14 ??= new int[0]; + BindCore(section12, ref temp14, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp14; } else { instance.MyArray = instance.MyArray; } - if (instance.MyArray is null && TryGetConfigurationValue(value8, key: null, out string? value12) && value12 == string.Empty) + if (instance.MyArray is null && TryGetConfigurationValue(value11, key: null, out string? value15) && value15 == string.Empty) { instance.MyArray = global::System.Array.Empty(); } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -255,11 +255,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_TypeOf.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_TypeOf.generated.txt index aa8ad68a97fb6f..41737d71cda678 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_TypeOf.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_TypeOf.generated.txt @@ -72,9 +72,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value1) && TryParseInt(value1, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp2; } } else if (defaultValueIfNotFound) @@ -154,11 +154,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_TypeOf_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_TypeOf_BinderOptions.generated.txt index b95a885ec261a7..d344b8c37d7c5f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_TypeOf_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ConfigurationBinder/Version1/Get_TypeOf_BinderOptions.generated.txt @@ -72,9 +72,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value1) && TryParseInt(value1, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp2; } } else if (defaultValueIfNotFound) @@ -154,11 +154,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/BindConfiguration.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/BindConfiguration.generated.txt index 9d8efcab38e621..1d7d0bca140b54 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/BindConfiguration.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/BindConfiguration.generated.txt @@ -35,10 +35,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")] file static class BindingExtensions { - #region OptionsBuilder extensions. + #region global::Microsoft.Extensions.Options.OptionsBuilder extensions. /// Registers the dependency injection container to bind against the obtained from the DI service provider. [InterceptsLocation(@"src-0.cs", 12, 24)] - public static OptionsBuilder BindConfiguration(this OptionsBuilder optionsBuilder, string configSectionPath, Action? configureBinder = null) where TOptions : class + public static global::Microsoft.Extensions.Options.OptionsBuilder BindConfiguration(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, string configSectionPath, Action? configureBinder = null) where TOptions : class { if (optionsBuilder is null) { @@ -68,10 +68,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return optionsBuilder; } - #endregion OptionsBuilder extensions. + #endregion global::Microsoft.Extensions.Options.OptionsBuilder extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -101,20 +101,23 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) + { + instance.Add(temp1); + } } } } public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -125,37 +128,57 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value2) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) + { + instance.MyInt = temp4; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section3) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; + } + else + { + instance.MyList = instance.MyList; } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -202,15 +225,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/BindConfigurationWithConfigureActions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/BindConfigurationWithConfigureActions.generated.txt index 9d8efcab38e621..1d7d0bca140b54 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/BindConfigurationWithConfigureActions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/BindConfigurationWithConfigureActions.generated.txt @@ -35,10 +35,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")] file static class BindingExtensions { - #region OptionsBuilder extensions. + #region global::Microsoft.Extensions.Options.OptionsBuilder extensions. /// Registers the dependency injection container to bind against the obtained from the DI service provider. [InterceptsLocation(@"src-0.cs", 12, 24)] - public static OptionsBuilder BindConfiguration(this OptionsBuilder optionsBuilder, string configSectionPath, Action? configureBinder = null) where TOptions : class + public static global::Microsoft.Extensions.Options.OptionsBuilder BindConfiguration(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, string configSectionPath, Action? configureBinder = null) where TOptions : class { if (optionsBuilder is null) { @@ -68,10 +68,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return optionsBuilder; } - #endregion OptionsBuilder extensions. + #endregion global::Microsoft.Extensions.Options.OptionsBuilder extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -101,20 +101,23 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) + { + instance.Add(temp1); + } } } } public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -125,37 +128,57 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value2) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) + { + instance.MyInt = temp4; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section3) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; + } + else + { + instance.MyList = instance.MyList; } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -202,15 +225,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/Bind_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/Bind_T.generated.txt index 6ea010083977c3..41fa60dc1c05e3 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/Bind_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/Bind_T.generated.txt @@ -35,16 +35,16 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")] file static class BindingExtensions { - #region OptionsBuilder extensions. + #region global::Microsoft.Extensions.Options.OptionsBuilder extensions. /// Registers a configuration instance which will bind against. [InterceptsLocation(@"src-0.cs", 15, 24)] - public static OptionsBuilder Bind(this OptionsBuilder optionsBuilder, IConfiguration config) where TOptions : class + public static global::Microsoft.Extensions.Options.OptionsBuilder Bind(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, IConfiguration config) where TOptions : class { return Bind(optionsBuilder, config, configureBinder: null); } /// Registers a configuration instance which will bind against. - public static OptionsBuilder Bind(this OptionsBuilder optionsBuilder, IConfiguration config, Action? configureBinder) where TOptions : class + public static global::Microsoft.Extensions.Options.OptionsBuilder Bind(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, IConfiguration config, Action? configureBinder) where TOptions : class { if (optionsBuilder is null) { @@ -54,7 +54,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration Configure(optionsBuilder.Services, optionsBuilder.Name, config, configureBinder); return optionsBuilder; } - #endregion OptionsBuilder extensions. + #endregion global::Microsoft.Extensions.Options.OptionsBuilder extensions. #region IServiceCollection extensions. /// Registers a configuration instance which TOptions will bind against. @@ -77,7 +77,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -107,20 +107,23 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) + { + instance.Add(temp1); + } } } } public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -131,37 +134,57 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value2) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) + { + instance.MyInt = temp4; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section3) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; + } + else + { + instance.MyList = instance.MyList; } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -208,15 +231,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/Bind_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/Bind_T_BinderOptions.generated.txt index d05f521ceb110c..c2e342e0e4dd39 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/Bind_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version0/Bind_T_BinderOptions.generated.txt @@ -35,10 +35,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")] file static class BindingExtensions { - #region OptionsBuilder extensions. + #region global::Microsoft.Extensions.Options.OptionsBuilder extensions. /// Registers a configuration instance which will bind against. [InterceptsLocation(@"src-0.cs", 15, 24)] - public static OptionsBuilder Bind(this OptionsBuilder optionsBuilder, IConfiguration config, Action? configureBinder) where TOptions : class + public static global::Microsoft.Extensions.Options.OptionsBuilder Bind(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, IConfiguration config, Action? configureBinder) where TOptions : class { if (optionsBuilder is null) { @@ -48,7 +48,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration Configure(optionsBuilder.Services, optionsBuilder.Name, config, configureBinder); return optionsBuilder; } - #endregion OptionsBuilder extensions. + #endregion global::Microsoft.Extensions.Options.OptionsBuilder extensions. #region IServiceCollection extensions. /// Registers a configuration instance which TOptions will bind against. @@ -71,7 +71,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -101,20 +101,23 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) + { + instance.Add(temp1); + } } } } public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -125,37 +128,57 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value2) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) + { + instance.MyInt = temp4; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section3) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; + } + else + { + instance.MyList = instance.MyList; } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -202,15 +225,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/BindConfiguration.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/BindConfiguration.generated.txt index 0a2c4f8f3f95a8..f2fc8d94587420 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/BindConfiguration.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/BindConfiguration.generated.txt @@ -103,9 +103,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -115,9 +115,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -128,11 +128,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -140,13 +140,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -225,11 +225,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/BindConfigurationWithConfigureActions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/BindConfigurationWithConfigureActions.generated.txt index b357b97fc261a0..de3a1e58e9d1e3 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/BindConfigurationWithConfigureActions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/BindConfigurationWithConfigureActions.generated.txt @@ -103,9 +103,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -115,9 +115,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -128,11 +128,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -140,13 +140,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -225,11 +225,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/Bind_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/Bind_T.generated.txt index 013ef9e450173f..584d71ec992039 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/Bind_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/Bind_T.generated.txt @@ -109,9 +109,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -121,9 +121,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -134,11 +134,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -146,13 +146,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -231,11 +231,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/Bind_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/Bind_T_BinderOptions.generated.txt index eccfa299c31c60..1e41b71def6258 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/Bind_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/OptionsBuilder/Version1/Bind_T_BinderOptions.generated.txt @@ -103,9 +103,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -115,9 +115,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -128,11 +128,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -140,13 +140,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -225,11 +225,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T.generated.txt index 3cdb19e7a96fc9..ed9826c1db4fd6 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T.generated.txt @@ -64,8 +64,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -95,20 +95,26 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) + { + instance.Add(temp1); + } } } } public static void BindCore(IConfiguration configuration, ref global::Program.MyClass2 instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (configuration["MyInt"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) + { + instance.MyInt = temp3; + } } else if (defaultValueIfNotFound) { @@ -134,7 +140,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance[section.Key] = value; } @@ -143,11 +149,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value3) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -158,53 +164,83 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value4) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) + { + instance.MyInt = temp7; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section5) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp7 = instance.MyList; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp7; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; + } + else + { + instance.MyList = instance.MyList; } - if (AsConfigWithChildren(configuration.GetSection("MyList2")) is IConfigurationSection section8) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp10 = instance.MyList2; - temp10 ??= new global::System.Collections.Generic.List(); - BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp10; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; + } + else + { + instance.MyList2 = instance.MyList2; } - if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section11) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } + else + { + instance.MyDictionary = instance.MyDictionary; + } + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -251,15 +287,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_BinderOptions.generated.txt index 7796b06b64f74e..d4ba4c0a745d0e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_BinderOptions.generated.txt @@ -64,8 +64,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -95,20 +95,26 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) + { + instance.Add(temp1); + } } } } public static void BindCore(IConfiguration configuration, ref global::Program.MyClass2 instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (configuration["MyInt"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) + { + instance.MyInt = temp3; + } } else if (defaultValueIfNotFound) { @@ -134,7 +140,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance[section.Key] = value; } @@ -143,11 +149,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value3) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -158,53 +164,83 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value4) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) + { + instance.MyInt = temp7; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section5) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp7 = instance.MyList; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp7; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; + } + else + { + instance.MyList = instance.MyList; } - if (AsConfigWithChildren(configuration.GetSection("MyList2")) is IConfigurationSection section8) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp10 = instance.MyList2; - temp10 ??= new global::System.Collections.Generic.List(); - BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp10; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; + } + else + { + instance.MyList2 = instance.MyList2; } - if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section11) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } + else + { + instance.MyDictionary = instance.MyDictionary; + } + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -251,15 +287,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_name.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_name.generated.txt index 2e317ed0c14ad7..367378b016aa08 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_name.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_name.generated.txt @@ -64,8 +64,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -95,20 +95,26 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) + { + instance.Add(temp1); + } } } } public static void BindCore(IConfiguration configuration, ref global::Program.MyClass2 instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (configuration["MyInt"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) + { + instance.MyInt = temp3; + } } else if (defaultValueIfNotFound) { @@ -134,7 +140,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance[section.Key] = value; } @@ -143,11 +149,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value3) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -158,53 +164,83 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value4) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) + { + instance.MyInt = temp7; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section5) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp7 = instance.MyList; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp7; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; + } + else + { + instance.MyList = instance.MyList; } - if (AsConfigWithChildren(configuration.GetSection("MyList2")) is IConfigurationSection section8) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp10 = instance.MyList2; - temp10 ??= new global::System.Collections.Generic.List(); - BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp10; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; + } + else + { + instance.MyList2 = instance.MyList2; } - if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section11) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } + else + { + instance.MyDictionary = instance.MyDictionary; + } + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -251,15 +287,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_name_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_name_BinderOptions.generated.txt index 099fc15a892f1b..9ae75b6fab000a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_name_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version0/Configure_T_name_BinderOptions.generated.txt @@ -58,8 +58,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -89,20 +89,26 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) + { + instance.Add(temp1); + } } } } public static void BindCore(IConfiguration configuration, ref global::Program.MyClass2 instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_ProgramMyClass2, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (configuration["MyInt"] is string value1) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) + { + instance.MyInt = temp3; + } } else if (defaultValueIfNotFound) { @@ -128,7 +134,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance[section.Key] = value; } @@ -137,11 +143,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["MyString"] is string value3) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -152,53 +158,83 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["MyInt"] is string value4) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) + { + instance.MyInt = temp7; + } } else if (defaultValueIfNotFound) { instance.MyInt = instance.MyInt; } - if (AsConfigWithChildren(configuration.GetSection("MyList")) is IConfigurationSection section5) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp7 = instance.MyList; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp7; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; + } + else + { + instance.MyList = instance.MyList; } - if (AsConfigWithChildren(configuration.GetSection("MyList2")) is IConfigurationSection section8) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp10 = instance.MyList2; - temp10 ??= new global::System.Collections.Generic.List(); - BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp10; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; + } + else + { + instance.MyList2 = instance.MyList2; } - if (AsConfigWithChildren(configuration.GetSection("MyDictionary")) is IConfigurationSection section11) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } + else + { + instance.MyDictionary = instance.MyDictionary; + } + } + + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; } /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -245,15 +281,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T.generated.txt index c7848d855b7ebd..1b396ff789aafb 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T.generated.txt @@ -97,9 +97,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -109,11 +109,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -151,9 +151,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -164,11 +164,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -176,39 +176,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -287,11 +287,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_BinderOptions.generated.txt index 074cead2a39a8b..989b49b892ac71 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_BinderOptions.generated.txt @@ -97,9 +97,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -109,11 +109,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -151,9 +151,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -164,11 +164,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -176,39 +176,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -287,11 +287,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_name.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_name.generated.txt index 8500b226e943a5..825808185c93fd 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_name.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_name.generated.txt @@ -97,9 +97,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -109,11 +109,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -151,9 +151,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -164,11 +164,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -176,39 +176,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -287,11 +287,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_name_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_name_BinderOptions.generated.txt index 8a6cbcdd238908..33738e12badb8a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_name_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/ServiceCollection/Version1/Configure_T_name_BinderOptions.generated.txt @@ -91,9 +91,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -103,11 +103,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -145,9 +145,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -158,11 +158,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -170,39 +170,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -281,11 +281,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/Collections.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/Collections.generated.txt index b241f66b2fc8dc..db7def58452758 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/Collections.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/Collections.generated.txt @@ -41,7 +41,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClassWithCustomCollections = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "CustomDictionary", "CustomList", "ICustomDictionary", "ICustomCollection", "IReadOnlyList", "UnsupportedIReadOnlyDictionaryUnsupported", "IReadOnlyDictionary", "CollectionStructExplicit" }); + private readonly static Lazy> s_configKeys_Program__MyClassWithCustomCollections = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "CustomDictionary", "CustomList", "ICustomDictionary", "ICustomCollection", "IReadOnlyList", "UnsupportedIReadOnlyDictionaryUnsupported", "IReadOnlyDictionary", "CollectionStructExplicit" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -71,9 +71,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - instance[section.Key] = ParseInt(value, section.Path); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) + { + instance[section.Key] = temp1; + } } } } @@ -82,7 +85,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance.Add(value); } @@ -91,32 +94,38 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.IReadOnlyList instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - if (instance is not ICollection temp) + if (instance is not global::System.Collections.Generic.ICollection temp) { return; } foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - temp.Add(ParseInt(value, section.Path)); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) + { + temp.Add(temp2); + } } } } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.IReadOnlyDictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - if (instance is not IDictionary temp) + if (instance is not global::System.Collections.Generic.IDictionary temp) { return; } foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { - temp[section.Key] = ParseInt(value, section.Path); + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) + { + temp[section.Key] = temp3; + } } } } @@ -127,7 +136,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { temp.Add(value); } @@ -136,63 +145,100 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Program.MyClassWithCustomCollections instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClassWithCustomCollections), s_configKeys_ProgramMyClassWithCustomCollections, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClassWithCustomCollections), s_configKeys_Program__MyClassWithCustomCollections, configuration, binderOptions); - if (AsConfigWithChildren(configuration.GetSection("CustomDictionary")) is IConfigurationSection section1) + var value4 = configuration.GetSection("CustomDictionary"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) + { + global::Program.CustomDictionary? temp7 = instance.CustomDictionary; + temp7 ??= new global::Program.CustomDictionary(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.CustomDictionary = temp7; + } + else { - global::Program.CustomDictionary? temp3 = instance.CustomDictionary; - temp3 ??= new global::Program.CustomDictionary(); - BindCore(section1, ref temp3, defaultValueIfNotFound: false, binderOptions); - instance.CustomDictionary = temp3; + instance.CustomDictionary = instance.CustomDictionary; } - if (AsConfigWithChildren(configuration.GetSection("CustomList")) is IConfigurationSection section4) + var value8 = configuration.GetSection("CustomList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) + { + global::Program.CustomList? temp11 = instance.CustomList; + temp11 ??= new global::Program.CustomList(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.CustomList = temp11; + } + else { - global::Program.CustomList? temp6 = instance.CustomList; - temp6 ??= new global::Program.CustomList(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.CustomList = temp6; + instance.CustomList = instance.CustomList; } - if (AsConfigWithChildren(configuration.GetSection("IReadOnlyList")) is IConfigurationSection section7) + var value12 = configuration.GetSection("IReadOnlyList"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.IReadOnlyList? temp9 = instance.IReadOnlyList; - temp9 = temp9 is null ? (global::System.Collections.Generic.IReadOnlyList)new List() : (global::System.Collections.Generic.IReadOnlyList)new List(temp9); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.IReadOnlyList = temp9; + global::System.Collections.Generic.IReadOnlyList? temp15 = instance.IReadOnlyList; + temp15 = temp15 is null ? (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List() : (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List(temp15); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.IReadOnlyList = temp15; + } + else + { + instance.IReadOnlyList = instance.IReadOnlyList; } - if (AsConfigWithChildren(configuration.GetSection("IReadOnlyDictionary")) is IConfigurationSection section10) + var value16 = configuration.GetSection("IReadOnlyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.IReadOnlyDictionary? temp12 = instance.IReadOnlyDictionary; - temp12 = temp12 is null ? (global::System.Collections.Generic.IReadOnlyDictionary)new Dictionary() : (global::System.Collections.Generic.IReadOnlyDictionary)temp12.ToDictionary(pair => pair.Key, pair => pair.Value); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.IReadOnlyDictionary = temp12; + global::System.Collections.Generic.IReadOnlyDictionary? temp19 = instance.IReadOnlyDictionary; + temp19 = temp19 is null ? (global::System.Collections.Generic.IReadOnlyDictionary)new global::System.Collections.Generic.Dictionary() : (global::System.Collections.Generic.IReadOnlyDictionary)temp19.ToDictionary(pair => pair.Key, pair => pair.Value); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.IReadOnlyDictionary = temp19; + } + else + { + instance.IReadOnlyDictionary = instance.IReadOnlyDictionary; } - if (AsConfigWithChildren(configuration.GetSection("CollectionStructExplicit")) is IConfigurationSection section13) + var value20 = configuration.GetSection("CollectionStructExplicit"); + if (AsConfigWithChildren(value20) is IConfigurationSection section21) { - global::Program.CollectionStructExplicit temp14 = instance.CollectionStructExplicit; - var temp15 = new global::Program.CollectionStructExplicit(); - BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); - instance.CollectionStructExplicit = temp15; - temp14 = temp15; + global::Program.CollectionStructExplicit temp22 = instance.CollectionStructExplicit; + var temp23 = new global::Program.CollectionStructExplicit(); + BindCore(section21, ref temp23, defaultValueIfNotFound: false, binderOptions); + instance.CollectionStructExplicit = temp23; + temp22 = temp23; + } + else + { + instance.CollectionStructExplicit = instance.CollectionStructExplicit; } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -239,15 +285,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/DefaultConstructorParameters.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/DefaultConstructorParameters.generated.txt index 3780c1a56ce14e..3145ca1512eca3 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/DefaultConstructorParameters.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/DefaultConstructorParameters.generated.txt @@ -36,7 +36,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #region IConfiguration extensions. /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively. [InterceptsLocation(@"src-0.cs", 13, 16)] - public static void Bind_ProgramClassWhereParametersHaveDefaultValue(this IConfiguration configuration, object? instance) + public static void Bind_Program__ClassWhereParametersHaveDefaultValue(this IConfiguration configuration, object? instance) { if (configuration is null) { @@ -54,115 +54,201 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramClassWhereParametersHaveDefaultValue = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "Name", "Address", "Age", "F", "D", "M", "SC", "C", "NAge", "NF", "ND", "NM", "NSC", "NC" }); + private readonly static Lazy> s_configKeys_Program__ClassWhereParametersHaveDefaultValue = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "Name", "Address", "Age", "F", "D", "M", "SC", "C", "NAge", "NF", "ND", "NM", "NSC", "NC" }); public static void BindCore(IConfiguration configuration, ref global::Program.ClassWhereParametersHaveDefaultValue instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.ClassWhereParametersHaveDefaultValue), s_configKeys_ProgramClassWhereParametersHaveDefaultValue, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.ClassWhereParametersHaveDefaultValue), s_configKeys_Program__ClassWhereParametersHaveDefaultValue, configuration, binderOptions); } - public static global::Program.ClassWhereParametersHaveDefaultValue InitializeProgramClassWhereParametersHaveDefaultValue(IConfiguration configuration, BinderOptions? binderOptions) + public static global::Program.ClassWhereParametersHaveDefaultValue InitializeProgram__ClassWhereParametersHaveDefaultValue(IConfiguration configuration, BinderOptions? binderOptions) { string name = "John Doe"!; - if (configuration["Name"] is string value0) + if (TryGetConfigurationValue(configuration, key: "Name", out string? value0)) { - name = value0; + if (value0 is null) + { + name = "John Doe"; + } + else + { + name = value0; + } } string address = "1 Microsoft Way"!; - if (configuration["Address"] is string value1) + if (TryGetConfigurationValue(configuration, key: "Address", out string? value1)) { - address = value1; + if (value1 is null) + { + address = "1 Microsoft Way"; + } + else + { + address = value1; + } } int age = (int)(42); - if (configuration["Age"] is string value2) + if (TryGetConfigurationValue(configuration, key: "Age", out string? value2) && value2 is not null && TryParseInt(value2, configuration.GetSection("Age").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - age = ParseInt(value2, configuration.GetSection("Age").Path); + age = temp3; } float f = 42F; - if (configuration["F"] is string value3) + if (TryGetConfigurationValue(configuration, key: "F", out string? value4) && value4 is not null && TryParseFloat(value4, configuration.GetSection("F").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp5)) { - f = ParseFloat(value3, configuration.GetSection("F").Path); + f = temp5; } double d = 3.1415899999999999D; - if (configuration["D"] is string value4) + if (TryGetConfigurationValue(configuration, key: "D", out string? value6) && value6 is not null && TryParseDouble(value6, configuration.GetSection("D").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp7)) { - d = ParseDouble(value4, configuration.GetSection("D").Path); + d = temp7; } decimal m = 3.1415926535897932384626433M; - if (configuration["M"] is string value5) + if (TryGetConfigurationValue(configuration, key: "M", out string? value8) && value8 is not null && TryParseDecimal(value8, configuration.GetSection("M").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp9)) { - m = ParseDecimal(value5, configuration.GetSection("M").Path); + m = temp9; } global::System.StringComparison sc = (global::System.StringComparison)(4); - if (configuration["SC"] is string value6) + if (TryGetConfigurationValue(configuration, key: "SC", out string? value10) && value10 is not null && TryParseEnum(value10, configuration.GetSection("SC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.StringComparison temp11)) { - sc = ParseEnum(value6, configuration.GetSection("SC").Path); + sc = temp11; } char c = 'q'; - if (configuration["C"] is string value7) + if (TryGetConfigurationValue(configuration, key: "C", out string? value12) && value12 is not null && TryParseChar(value12, configuration.GetSection("C").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp13)) { - c = ParseChar(value7, configuration.GetSection("C").Path); + c = temp13; } int? nage = (int?)(42); - if (configuration["NAge"] is string value8) + if (TryGetConfigurationValue(configuration, key: "NAge", out string? value14)) { - nage = ParseInt(value8, configuration.GetSection("NAge").Path); + if (string.IsNullOrEmpty(value14)) + { + nage = (int?)(42); + } + else + { + if (TryParseInt(value14, configuration.GetSection("NAge").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp15)) + { + nage = temp15; + } + } } float? nf = 42F; - if (configuration["NF"] is string value9) + if (TryGetConfigurationValue(configuration, key: "NF", out string? value16)) { - nf = ParseFloat(value9, configuration.GetSection("NF").Path); + if (string.IsNullOrEmpty(value16)) + { + nf = 42F; + } + else + { + if (TryParseFloat(value16, configuration.GetSection("NF").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp17)) + { + nf = temp17; + } + } } double? nd = 3.1415899999999999D; - if (configuration["ND"] is string value10) + if (TryGetConfigurationValue(configuration, key: "ND", out string? value18)) { - nd = ParseDouble(value10, configuration.GetSection("ND").Path); + if (string.IsNullOrEmpty(value18)) + { + nd = 3.1415899999999999D; + } + else + { + if (TryParseDouble(value18, configuration.GetSection("ND").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp19)) + { + nd = temp19; + } + } } decimal? nm = 3.1415926535897932384626433M; - if (configuration["NM"] is string value11) + if (TryGetConfigurationValue(configuration, key: "NM", out string? value20)) { - nm = ParseDecimal(value11, configuration.GetSection("NM").Path); + if (string.IsNullOrEmpty(value20)) + { + nm = 3.1415926535897932384626433M; + } + else + { + if (TryParseDecimal(value20, configuration.GetSection("NM").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp21)) + { + nm = temp21; + } + } } global::System.StringComparison? nsc = (global::System.StringComparison?)(4); - if (configuration["NSC"] is string value12) + if (TryGetConfigurationValue(configuration, key: "NSC", out string? value22)) { - nsc = ParseEnum(value12, configuration.GetSection("NSC").Path); + if (string.IsNullOrEmpty(value22)) + { + nsc = (global::System.StringComparison?)(4); + } + else + { + if (TryParseEnum(value22, configuration.GetSection("NSC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.StringComparison temp23)) + { + nsc = temp23; + } + } } char? nc = 'q'; - if (configuration["NC"] is string value13) + if (TryGetConfigurationValue(configuration, key: "NC", out string? value24)) { - nc = ParseChar(value13, configuration.GetSection("NC").Path); + if (string.IsNullOrEmpty(value24)) + { + nc = 'q'; + } + else + { + if (TryParseChar(value24, configuration.GetSection("NC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp25)) + { + nc = temp25; + } + } } return new global::Program.ClassWhereParametersHaveDefaultValue(name, address, age, f, d, m, sc, c, nage, nf, nd, nm, nsc, nc); } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -173,75 +259,111 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, string? path) where T : struct + public static bool TryParseEnum(string value, string? path, bool errorOnFailedBinding, out T result) where T : struct { try { - return (T)Enum.Parse(typeof(T), value, ignoreCase: true); + result = (T)Enum.Parse(typeof(T), value, ignoreCase: true); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(T)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(T)}'.", exception); } } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(float)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(float)}'.", exception); } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(double)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(double)}'.", exception); } } - public static decimal ParseDecimal(string value, string? path) + public static bool TryParseDecimal(string value, string? path, bool errorOnFailedBinding, out decimal result) { try { - return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(decimal)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(decimal)}'.", exception); } } - public static char ParseChar(string value, string? path) + public static bool TryParseChar(string value, string? path, bool errorOnFailedBinding, out char result) { try { - return char.Parse(value); + result = char.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(char)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(char)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/EmptyConfigType.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/EmptyConfigType.generated.txt index 027b41bb5e13d8..83f5541d533a17 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/EmptyConfigType.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/EmptyConfigType.generated.txt @@ -61,31 +61,44 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_TypeWithNoMembers_Wrapper = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "Member" }); + private readonly static Lazy> s_configKeys_TypeWithNoMembers_Wrapper = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "Member" }); public static void BindCore(IConfiguration configuration, ref global::TypeWithNoMembers_Wrapper instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { ValidateConfigurationKeys(typeof(global::TypeWithNoMembers_Wrapper), s_configKeys_TypeWithNoMembers_Wrapper, configuration, binderOptions); - if (AsConfigWithChildren(configuration.GetSection("Member")) is IConfigurationSection section0) + var value0 = configuration.GetSection("Member"); + if (AsConfigWithChildren(value0) is IConfigurationSection section1) { instance.Member ??= new global::TypeWithNoMembers(); } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/Primitives.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/Primitives.generated.txt index a921ccfad060c1..2edc3f172f16be 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/Primitives.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/Primitives.generated.txt @@ -36,7 +36,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #region IConfiguration extensions. /// Attempts to bind the given object instance to configuration values by matching property names against configuration keys recursively. [InterceptsLocation(@"src-0.cs", 13, 16)] - public static void Bind_ProgramMyClass(this IConfiguration configuration, object? instance) + public static void Bind_Program__MyClass(this IConfiguration configuration, object? instance) { if (configuration is null) { @@ -54,60 +54,75 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_ProgramMyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "Prop0", "Prop1", "Prop2", "Prop3", "Prop4", "Prop5", "Prop6", "Prop8", "Prop9", "Prop10", "Prop13", "Prop14", "Prop15", "Prop16", "Prop17", "Prop19", "Prop20", "Prop21", "Prop23", "Prop24", "Prop25", "Prop26", "Prop27", "Prop28", "Prop29", "Prop30" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "Prop0", "Prop1", "Prop2", "Prop3", "Prop4", "Prop5", "Prop6", "Prop8", "Prop9", "Prop10", "Prop13", "Prop14", "Prop15", "Prop16", "Prop17", "Prop19", "Prop20", "Prop21", "Prop23", "Prop24", "Prop25", "Prop26", "Prop27", "Prop28", "Prop29", "Prop30" }); public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_ProgramMyClass, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (configuration["Prop0"] is string value0) + if (TryGetConfigurationValue(configuration, key: "Prop0", out string? value0)) { - instance.Prop0 = ParseBool(value0, configuration.GetSection("Prop0").Path); + if (!string.IsNullOrEmpty(value0) && TryParseBool(value0, configuration.GetSection("Prop0").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out bool temp1)) + { + instance.Prop0 = temp1; + } } else if (defaultValueIfNotFound) { instance.Prop0 = instance.Prop0; } - if (configuration["Prop1"] is string value1) + if (TryGetConfigurationValue(configuration, key: "Prop1", out string? value2)) { - instance.Prop1 = ParseByte(value1, configuration.GetSection("Prop1").Path); + if (!string.IsNullOrEmpty(value2) && TryParseByte(value2, configuration.GetSection("Prop1").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte temp3)) + { + instance.Prop1 = temp3; + } } else if (defaultValueIfNotFound) { instance.Prop1 = instance.Prop1; } - if (configuration["Prop2"] is string value2) + if (TryGetConfigurationValue(configuration, key: "Prop2", out string? value4)) { - instance.Prop2 = ParseSbyte(value2, configuration.GetSection("Prop2").Path); + if (!string.IsNullOrEmpty(value4) && TryParseSbyte(value4, configuration.GetSection("Prop2").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out sbyte temp5)) + { + instance.Prop2 = temp5; + } } else if (defaultValueIfNotFound) { instance.Prop2 = instance.Prop2; } - if (configuration["Prop3"] is string value3) + if (TryGetConfigurationValue(configuration, key: "Prop3", out string? value6)) { - instance.Prop3 = ParseChar(value3, configuration.GetSection("Prop3").Path); + if (!string.IsNullOrEmpty(value6) && TryParseChar(value6, configuration.GetSection("Prop3").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp7)) + { + instance.Prop3 = temp7; + } } else if (defaultValueIfNotFound) { instance.Prop3 = instance.Prop3; } - if (configuration["Prop4"] is string value4) + if (TryGetConfigurationValue(configuration, key: "Prop4", out string? value8)) { - instance.Prop4 = ParseDouble(value4, configuration.GetSection("Prop4").Path); + if (!string.IsNullOrEmpty(value8) && TryParseDouble(value8, configuration.GetSection("Prop4").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp9)) + { + instance.Prop4 = temp9; + } } else if (defaultValueIfNotFound) { instance.Prop4 = instance.Prop4; } - if (configuration["Prop5"] is string value5) + if (TryGetConfigurationValue(configuration, key: "Prop5", out string? value10)) { - instance.Prop5 = value5; + instance.Prop5 = value10; } else if (defaultValueIfNotFound) { @@ -118,72 +133,93 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["Prop6"] is string value6) + if (TryGetConfigurationValue(configuration, key: "Prop6", out string? value11)) { - instance.Prop6 = ParseInt(value6, configuration.GetSection("Prop6").Path); + if (!string.IsNullOrEmpty(value11) && TryParseInt(value11, configuration.GetSection("Prop6").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp12)) + { + instance.Prop6 = temp12; + } } else if (defaultValueIfNotFound) { instance.Prop6 = instance.Prop6; } - if (configuration["Prop8"] is string value7) + if (TryGetConfigurationValue(configuration, key: "Prop8", out string? value13)) { - instance.Prop8 = ParseShort(value7, configuration.GetSection("Prop8").Path); + if (!string.IsNullOrEmpty(value13) && TryParseShort(value13, configuration.GetSection("Prop8").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out short temp14)) + { + instance.Prop8 = temp14; + } } else if (defaultValueIfNotFound) { instance.Prop8 = instance.Prop8; } - if (configuration["Prop9"] is string value8) + if (TryGetConfigurationValue(configuration, key: "Prop9", out string? value15)) { - instance.Prop9 = ParseLong(value8, configuration.GetSection("Prop9").Path); + if (!string.IsNullOrEmpty(value15) && TryParseLong(value15, configuration.GetSection("Prop9").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out long temp16)) + { + instance.Prop9 = temp16; + } } else if (defaultValueIfNotFound) { instance.Prop9 = instance.Prop9; } - if (configuration["Prop10"] is string value9) + if (TryGetConfigurationValue(configuration, key: "Prop10", out string? value17)) { - instance.Prop10 = ParseFloat(value9, configuration.GetSection("Prop10").Path); + if (!string.IsNullOrEmpty(value17) && TryParseFloat(value17, configuration.GetSection("Prop10").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp18)) + { + instance.Prop10 = temp18; + } } else if (defaultValueIfNotFound) { instance.Prop10 = instance.Prop10; } - if (configuration["Prop13"] is string value10) + if (TryGetConfigurationValue(configuration, key: "Prop13", out string? value19)) { - instance.Prop13 = ParseUshort(value10, configuration.GetSection("Prop13").Path); + if (!string.IsNullOrEmpty(value19) && TryParseUshort(value19, configuration.GetSection("Prop13").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out ushort temp20)) + { + instance.Prop13 = temp20; + } } else if (defaultValueIfNotFound) { instance.Prop13 = instance.Prop13; } - if (configuration["Prop14"] is string value11) + if (TryGetConfigurationValue(configuration, key: "Prop14", out string? value21)) { - instance.Prop14 = ParseUint(value11, configuration.GetSection("Prop14").Path); + if (!string.IsNullOrEmpty(value21) && TryParseUint(value21, configuration.GetSection("Prop14").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out uint temp22)) + { + instance.Prop14 = temp22; + } } else if (defaultValueIfNotFound) { instance.Prop14 = instance.Prop14; } - if (configuration["Prop15"] is string value12) + if (TryGetConfigurationValue(configuration, key: "Prop15", out string? value23)) { - instance.Prop15 = ParseUlong(value12, configuration.GetSection("Prop15").Path); + if (!string.IsNullOrEmpty(value23) && TryParseUlong(value23, configuration.GetSection("Prop15").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out ulong temp24)) + { + instance.Prop15 = temp24; + } } else if (defaultValueIfNotFound) { instance.Prop15 = instance.Prop15; } - if (configuration["Prop16"] is string value13) + if (TryGetConfigurationValue(configuration, key: "Prop16", out string? value25)) { - instance.Prop16 = value13; + instance.Prop16 = value25; } else if (defaultValueIfNotFound) { @@ -194,9 +230,19 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["Prop17"] is string value14) + if (TryGetConfigurationValue(configuration, key: "Prop17", out string? value26)) { - instance.Prop17 = ParseSystemGlobalizationCultureInfo(value14, configuration.GetSection("Prop17").Path); + if (value26 is null) + { + instance.Prop17 = null; + } + else + { + if (!string.IsNullOrEmpty(value26) && TryParseSystemGlobalizationCultureInfo(value26, configuration.GetSection("Prop17").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Globalization.CultureInfo temp27)) + { + instance.Prop17 = temp27; + } + } } else if (defaultValueIfNotFound) { @@ -207,54 +253,79 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["Prop19"] is string value15) + if (TryGetConfigurationValue(configuration, key: "Prop19", out string? value28)) { - instance.Prop19 = ParseSystemDateTime(value15, configuration.GetSection("Prop19").Path); + if (!string.IsNullOrEmpty(value28) && TryParseSystemDateTime(value28, configuration.GetSection("Prop19").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTime temp29)) + { + instance.Prop19 = temp29; + } } else if (defaultValueIfNotFound) { instance.Prop19 = instance.Prop19; } - if (configuration["Prop20"] is string value16) + if (TryGetConfigurationValue(configuration, key: "Prop20", out string? value30)) { - instance.Prop20 = ParseSystemDateTimeOffset(value16, configuration.GetSection("Prop20").Path); + if (!string.IsNullOrEmpty(value30) && TryParseSystemDateTimeOffset(value30, configuration.GetSection("Prop20").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTimeOffset temp31)) + { + instance.Prop20 = temp31; + } } else if (defaultValueIfNotFound) { instance.Prop20 = instance.Prop20; } - if (configuration["Prop21"] is string value17) + if (TryGetConfigurationValue(configuration, key: "Prop21", out string? value32)) { - instance.Prop21 = ParseDecimal(value17, configuration.GetSection("Prop21").Path); + if (!string.IsNullOrEmpty(value32) && TryParseDecimal(value32, configuration.GetSection("Prop21").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp33)) + { + instance.Prop21 = temp33; + } } else if (defaultValueIfNotFound) { instance.Prop21 = instance.Prop21; } - if (configuration["Prop23"] is string value18) + if (TryGetConfigurationValue(configuration, key: "Prop23", out string? value34)) { - instance.Prop23 = ParseSystemTimeSpan(value18, configuration.GetSection("Prop23").Path); + if (!string.IsNullOrEmpty(value34) && TryParseSystemTimeSpan(value34, configuration.GetSection("Prop23").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.TimeSpan temp35)) + { + instance.Prop23 = temp35; + } } else if (defaultValueIfNotFound) { instance.Prop23 = instance.Prop23; } - if (configuration["Prop24"] is string value19) + if (TryGetConfigurationValue(configuration, key: "Prop24", out string? value36)) { - instance.Prop24 = ParseSystemGuid(value19, configuration.GetSection("Prop24").Path); + if (!string.IsNullOrEmpty(value36) && TryParseSystemGuid(value36, configuration.GetSection("Prop24").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Guid temp37)) + { + instance.Prop24 = temp37; + } } else if (defaultValueIfNotFound) { instance.Prop24 = instance.Prop24; } - if (configuration["Prop25"] is string value20) + if (TryGetConfigurationValue(configuration, key: "Prop25", out string? value38)) { - instance.Prop25 = ParseSystemUri(value20, configuration.GetSection("Prop25").Path); + if (value38 is null) + { + instance.Prop25 = null; + } + else + { + if (!string.IsNullOrEmpty(value38) && TryParseSystemUri(value38, configuration.GetSection("Prop25").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Uri temp39)) + { + instance.Prop25 = temp39; + } + } } else if (defaultValueIfNotFound) { @@ -265,9 +336,19 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["Prop26"] is string value21) + if (TryGetConfigurationValue(configuration, key: "Prop26", out string? value40)) { - instance.Prop26 = ParseSystemVersion(value21, configuration.GetSection("Prop26").Path); + if (value40 is null) + { + instance.Prop26 = null; + } + else + { + if (!string.IsNullOrEmpty(value40) && TryParseSystemVersion(value40, configuration.GetSection("Prop26").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Version temp41)) + { + instance.Prop26 = temp41; + } + } } else if (defaultValueIfNotFound) { @@ -278,18 +359,35 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["Prop27"] is string value22) + if (TryGetConfigurationValue(configuration, key: "Prop27", out string? value42)) { - instance.Prop27 = ParseEnum(value22, configuration.GetSection("Prop27").Path); + if (!string.IsNullOrEmpty(value42) && TryParseEnum(value42, configuration.GetSection("Prop27").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DayOfWeek temp43)) + { + instance.Prop27 = temp43; + } } else if (defaultValueIfNotFound) { instance.Prop27 = instance.Prop27; } - if (configuration["Prop28"] is string value23) + if (TryGetConfigurationValue(configuration, key: "Prop28", out string? value44)) { - instance.Prop28 = ParseByteArray(value23, configuration.GetSection("Prop28").Path); + if (value44 is null) + { + instance.Prop28 = null; + } + else + { + if (value44 == string.Empty && TryParseByteArray(value44, configuration.GetSection("Prop28").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte[] temp45)) + { + instance.Prop28 = temp45; + } + else if (!string.IsNullOrEmpty(value44) && TryParseByteArray(value44, configuration.GetSection("Prop28").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte[] temp46)) + { + instance.Prop28 = temp46; + } + } } else if (defaultValueIfNotFound) { @@ -300,18 +398,24 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["Prop29"] is string value24) + if (TryGetConfigurationValue(configuration, key: "Prop29", out string? value47)) { - instance.Prop29 = ParseInt(value24, configuration.GetSection("Prop29").Path); + if (!string.IsNullOrEmpty(value47) && TryParseInt(value47, configuration.GetSection("Prop29").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp48)) + { + instance.Prop29 = temp48; + } } else if (defaultValueIfNotFound) { instance.Prop29 = instance.Prop29; } - if (configuration["Prop30"] is string value25) + if (TryGetConfigurationValue(configuration, key: "Prop30", out string? value49)) { - instance.Prop30 = ParseSystemDateTime(value25, configuration.GetSection("Prop30").Path); + if (!string.IsNullOrEmpty(value49) && TryParseSystemDateTime(value49, configuration.GetSection("Prop30").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTime temp50)) + { + instance.Prop30 = temp50; + } } else if (defaultValueIfNotFound) { @@ -319,19 +423,31 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -342,267 +458,399 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, string? path) where T : struct + public static bool TryParseEnum(string value, string? path, bool errorOnFailedBinding, out T result) where T : struct { try { - return (T)Enum.Parse(typeof(T), value, ignoreCase: true); + result = (T)Enum.Parse(typeof(T), value, ignoreCase: true); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(T)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(T)}'.", exception); } } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(bool)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(bool)}'.", exception); } } - public static byte ParseByte(string value, string? path) + public static bool TryParseByte(string value, string? path, bool errorOnFailedBinding, out byte result) { try { - return byte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = byte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(byte)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(byte)}'.", exception); } } - public static sbyte ParseSbyte(string value, string? path) + public static bool TryParseSbyte(string value, string? path, bool errorOnFailedBinding, out sbyte result) { try { - return sbyte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = sbyte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(sbyte)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(sbyte)}'.", exception); } } - public static char ParseChar(string value, string? path) + public static bool TryParseChar(string value, string? path, bool errorOnFailedBinding, out char result) { try { - return char.Parse(value); + result = char.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(char)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(char)}'.", exception); } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(double)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(double)}'.", exception); } } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } - public static short ParseShort(string value, string? path) + public static bool TryParseShort(string value, string? path, bool errorOnFailedBinding, out short result) { try { - return short.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = short.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(short)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(short)}'.", exception); } } - public static long ParseLong(string value, string? path) + public static bool TryParseLong(string value, string? path, bool errorOnFailedBinding, out long result) { try { - return long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(long)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(long)}'.", exception); } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(float)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(float)}'.", exception); } } - public static ushort ParseUshort(string value, string? path) + public static bool TryParseUshort(string value, string? path, bool errorOnFailedBinding, out ushort result) { try { - return ushort.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = ushort.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(ushort)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(ushort)}'.", exception); } } - public static uint ParseUint(string value, string? path) + public static bool TryParseUint(string value, string? path, bool errorOnFailedBinding, out uint result) { try { - return uint.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = uint.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(uint)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(uint)}'.", exception); } } - public static ulong ParseUlong(string value, string? path) + public static bool TryParseUlong(string value, string? path, bool errorOnFailedBinding, out ulong result) { try { - return ulong.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = ulong.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(ulong)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(ulong)}'.", exception); } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(global::System.Globalization.CultureInfo)}'.", exception); } } - public static global::System.DateTime ParseSystemDateTime(string value, string? path) + public static bool TryParseSystemDateTime(string value, string? path, bool errorOnFailedBinding, out global::System.DateTime result) { try { - return global::System.DateTime.Parse(value, CultureInfo.InvariantCulture); + result = global::System.DateTime.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.DateTime)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(global::System.DateTime)}'.", exception); } } - public static global::System.DateTimeOffset ParseSystemDateTimeOffset(string value, string? path) + public static bool TryParseSystemDateTimeOffset(string value, string? path, bool errorOnFailedBinding, out global::System.DateTimeOffset result) { try { - return global::System.DateTimeOffset.Parse(value, CultureInfo.InvariantCulture); + result = global::System.DateTimeOffset.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.DateTimeOffset)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(global::System.DateTimeOffset)}'.", exception); } } - public static decimal ParseDecimal(string value, string? path) + public static bool TryParseDecimal(string value, string? path, bool errorOnFailedBinding, out decimal result) { try { - return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(decimal)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(decimal)}'.", exception); } } - public static global::System.TimeSpan ParseSystemTimeSpan(string value, string? path) + public static bool TryParseSystemTimeSpan(string value, string? path, bool errorOnFailedBinding, out global::System.TimeSpan result) { try { - return global::System.TimeSpan.Parse(value, CultureInfo.InvariantCulture); + result = global::System.TimeSpan.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.TimeSpan)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(global::System.TimeSpan)}'.", exception); } } - public static global::System.Guid ParseSystemGuid(string value, string? path) + public static bool TryParseSystemGuid(string value, string? path, bool errorOnFailedBinding, out global::System.Guid result) { try { - return global::System.Guid.Parse(value); + result = global::System.Guid.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Guid)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(global::System.Guid)}'.", exception); } } - public static global::System.Uri ParseSystemUri(string value, string? path) + public static bool TryParseSystemUri(string value, string? path, bool errorOnFailedBinding, out global::System.Uri result) { try { - return new Uri(value, UriKind.RelativeOrAbsolute); + result = new Uri(value, UriKind.RelativeOrAbsolute); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Uri)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(global::System.Uri)}'.", exception); } } - public static global::System.Version ParseSystemVersion(string value, string? path) + public static bool TryParseSystemVersion(string value, string? path, bool errorOnFailedBinding, out global::System.Version result) { try { - return global::System.Version.Parse(value); + result = global::System.Version.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(global::System.Version)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(global::System.Version)}'.", exception); } } - public static byte[] ParseByteArray(string value, string? path) + public static bool TryParseByteArray(string value, string? path, bool errorOnFailedBinding, out byte[] result) { try { - return Convert.FromBase64String(value); + result = Convert.FromBase64String(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(byte[])}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(byte[])}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/UnsupportedTypes.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/UnsupportedTypes.generated.txt index ae61aaeaf23721..ff9b25d9a9e31d 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/UnsupportedTypes.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version0/UnsupportedTypes.generated.txt @@ -60,8 +60,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_RecordAction = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "x" }); - private readonly static Lazy> s_configKeys_Options = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "Name", "Age", "List", "Array", "Record" }); + private readonly static Lazy> s_configKeys_Record___System__Action___ = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "x" }); + private readonly static Lazy> s_configKeys_Options = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "Name", "Age", "List", "Array", "Record" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -97,7 +97,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { instance.Add(value); } @@ -110,7 +110,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration foreach (IConfigurationSection section in configuration.GetChildren()) { - if (section.Value is string value) + if (TryGetConfigurationValue(section, key: null, out string? value)) { temp1.Add(value); } @@ -123,14 +123,14 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::Record instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - ValidateConfigurationKeys(typeof(global::Record), s_configKeys_RecordAction, configuration, binderOptions); + ValidateConfigurationKeys(typeof(global::Record), s_configKeys_Record___System__Action___, configuration, binderOptions); } public static void BindCore(IConfiguration configuration, ref global::Options instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { ValidateConfigurationKeys(typeof(global::Options), s_configKeys_Options, configuration, binderOptions); - if (configuration["Name"] is string value2) + if (TryGetConfigurationValue(configuration, key: "Name", out string? value2)) { instance.Name = value2; } @@ -143,46 +143,68 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (configuration["Age"] is string value3) + if (TryGetConfigurationValue(configuration, key: "Age", out string? value3)) { - instance.Age = ParseInt(value3, configuration.GetSection("Age").Path); + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("Age").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) + { + instance.Age = temp4; + } } else if (defaultValueIfNotFound) { instance.Age = instance.Age; } - if (AsConfigWithChildren(configuration.GetSection("List")) is IConfigurationSection section4) + var value5 = configuration.GetSection("List"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.List; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.List = temp6; + global::System.Collections.Generic.List? temp8 = instance.List; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.List = temp8; } - - if (AsConfigWithChildren(configuration.GetSection("Array")) is IConfigurationSection section7) + else { - string[]? temp9 = instance.Array; - temp9 ??= new string[0]; - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.Array = temp9; + instance.List = instance.List; } - if (AsConfigWithChildren(configuration.GetSection("Record")) is IConfigurationSection section10) + var value9 = configuration.GetSection("Array"); + if (AsConfigWithChildren(value9) is IConfigurationSection section10) { - global::Record? temp12 = instance.Record; - temp12 ??= InitializeRecordAction(section10, binderOptions); + string[]? temp12 = instance.Array; + temp12 ??= new string[0]; BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.Record = temp12; + instance.Array = temp12; + } + else + { + instance.Array = instance.Array; + } + if (instance.Array is null && TryGetConfigurationValue(value9, key: null, out string? value13) && value13 == string.Empty) + { + instance.Array = global::System.Array.Empty(); + } + + var value14 = configuration.GetSection("Record"); + if (AsConfigWithChildren(value14) is IConfigurationSection section15) + { + global::Record? temp17 = instance.Record; + temp17 ??= InitializeRecord___System__Action___(section15, binderOptions); + BindCore(section15, ref temp17, defaultValueIfNotFound: false, binderOptions); + instance.Record = temp17; + } + else + { + instance.Record = instance.Record; } } - public static global::Record InitializeRecordAction(IConfiguration configuration, BinderOptions? binderOptions) + public static global::Record InitializeRecord___System__Action___(IConfiguration configuration, BinderOptions? binderOptions) { int x = (int)(10); - if (configuration["x"] is string value13) + if (TryGetConfigurationValue(configuration, key: "x", out string? value18) && value18 is not null && TryParseInt(value18, configuration.GetSection("x").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp19)) { - x = ParseInt(value13, configuration.GetSection("x").Path); + x = temp19; } return new global::Record(x) @@ -191,19 +213,31 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration }; } + /// Tries to get the configuration value for the specified key. + public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value) + { + if (configuration is ConfigurationSection section) + { + return section.TryGetValue(key, out value); + } + + value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null; + return value != null; + } + /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -250,15 +284,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{path}' to type '{typeof(int)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception); } } #endregion Core binding extensions. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/Collections.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/Collections.generated.txt index 668cbc6f836bd0..1f6034a907421a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/Collections.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/Collections.generated.txt @@ -73,9 +73,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance[section.Key] = ParseInt(value, section.Path); + instance[section.Key] = temp1; } } } @@ -103,9 +103,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - temp.Add(ParseInt(value, section.Path)); + temp.Add(temp2); } } } @@ -122,9 +122,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - temp[section.Key] = ParseInt(value, section.Path); + temp[section.Key] = temp3; } } } @@ -147,66 +147,66 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClassWithCustomCollections), s_configKeys_Program__MyClassWithCustomCollections, configuration, binderOptions); - var value1 = configuration.GetSection("CustomDictionary"); - if (AsConfigWithChildren(value1) is IConfigurationSection section2) + var value4 = configuration.GetSection("CustomDictionary"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::Program.CustomDictionary? temp4 = instance.CustomDictionary; - temp4 ??= new global::Program.CustomDictionary(); - BindCore(section2, ref temp4, defaultValueIfNotFound: false, binderOptions); - instance.CustomDictionary = temp4; + global::Program.CustomDictionary? temp7 = instance.CustomDictionary; + temp7 ??= new global::Program.CustomDictionary(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.CustomDictionary = temp7; } else { instance.CustomDictionary = instance.CustomDictionary; } - var value5 = configuration.GetSection("CustomList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("CustomList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::Program.CustomList? temp8 = instance.CustomList; - temp8 ??= new global::Program.CustomList(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.CustomList = temp8; + global::Program.CustomList? temp11 = instance.CustomList; + temp11 ??= new global::Program.CustomList(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.CustomList = temp11; } else { instance.CustomList = instance.CustomList; } - var value9 = configuration.GetSection("IReadOnlyList"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("IReadOnlyList"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.IReadOnlyList? temp12 = instance.IReadOnlyList; - temp12 = temp12 is null ? (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List() : (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List(temp12); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.IReadOnlyList = temp12; + global::System.Collections.Generic.IReadOnlyList? temp15 = instance.IReadOnlyList; + temp15 = temp15 is null ? (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List() : (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List(temp15); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.IReadOnlyList = temp15; } else { instance.IReadOnlyList = instance.IReadOnlyList; } - var value13 = configuration.GetSection("IReadOnlyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("IReadOnlyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.IReadOnlyDictionary? temp16 = instance.IReadOnlyDictionary; - temp16 = temp16 is null ? (global::System.Collections.Generic.IReadOnlyDictionary)new global::System.Collections.Generic.Dictionary() : (global::System.Collections.Generic.IReadOnlyDictionary)temp16.ToDictionary(pair => pair.Key, pair => pair.Value); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.IReadOnlyDictionary = temp16; + global::System.Collections.Generic.IReadOnlyDictionary? temp19 = instance.IReadOnlyDictionary; + temp19 = temp19 is null ? (global::System.Collections.Generic.IReadOnlyDictionary)new global::System.Collections.Generic.Dictionary() : (global::System.Collections.Generic.IReadOnlyDictionary)temp19.ToDictionary(pair => pair.Key, pair => pair.Value); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.IReadOnlyDictionary = temp19; } else { instance.IReadOnlyDictionary = instance.IReadOnlyDictionary; } - var value17 = configuration.GetSection("CollectionStructExplicit"); - if (AsConfigWithChildren(value17) is IConfigurationSection section18) + var value20 = configuration.GetSection("CollectionStructExplicit"); + if (AsConfigWithChildren(value20) is IConfigurationSection section21) { - global::Program.CollectionStructExplicit temp19 = instance.CollectionStructExplicit; - var temp20 = new global::Program.CollectionStructExplicit(); - BindCore(section18, ref temp20, defaultValueIfNotFound: false, binderOptions); - instance.CollectionStructExplicit = temp20; - temp19 = temp20; + global::Program.CollectionStructExplicit temp22 = instance.CollectionStructExplicit; + var temp23 = new global::Program.CollectionStructExplicit(); + BindCore(section21, ref temp23, defaultValueIfNotFound: false, binderOptions); + instance.CollectionStructExplicit = temp23; + temp22 = temp23; } else { @@ -285,11 +285,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/DefaultConstructorParameters.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/DefaultConstructorParameters.generated.txt index 7fa4bc64ab7d19..f365ec0232c0c2 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/DefaultConstructorParameters.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/DefaultConstructorParameters.generated.txt @@ -90,116 +90,134 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } int age = (int)(42); - if (TryGetConfigurationValue(configuration, key: "Age", out string? value2) && value2 is not null) + if (TryGetConfigurationValue(configuration, key: "Age", out string? value2) && value2 is not null && TryParseInt(value2, configuration.GetSection("Age").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - age = ParseInt(value2, configuration.GetSection("Age").Path); + age = temp3; } float f = 42F; - if (TryGetConfigurationValue(configuration, key: "F", out string? value3) && value3 is not null) + if (TryGetConfigurationValue(configuration, key: "F", out string? value4) && value4 is not null && TryParseFloat(value4, configuration.GetSection("F").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp5)) { - f = ParseFloat(value3, configuration.GetSection("F").Path); + f = temp5; } double d = 3.1415899999999999D; - if (TryGetConfigurationValue(configuration, key: "D", out string? value4) && value4 is not null) + if (TryGetConfigurationValue(configuration, key: "D", out string? value6) && value6 is not null && TryParseDouble(value6, configuration.GetSection("D").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp7)) { - d = ParseDouble(value4, configuration.GetSection("D").Path); + d = temp7; } decimal m = 3.1415926535897932384626433M; - if (TryGetConfigurationValue(configuration, key: "M", out string? value5) && value5 is not null) + if (TryGetConfigurationValue(configuration, key: "M", out string? value8) && value8 is not null && TryParseDecimal(value8, configuration.GetSection("M").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp9)) { - m = ParseDecimal(value5, configuration.GetSection("M").Path); + m = temp9; } global::System.StringComparison sc = (global::System.StringComparison)(4); - if (TryGetConfigurationValue(configuration, key: "SC", out string? value6) && value6 is not null) + if (TryGetConfigurationValue(configuration, key: "SC", out string? value10) && value10 is not null && TryParseEnum(value10, configuration.GetSection("SC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.StringComparison temp11)) { - sc = ParseEnum(value6, configuration.GetSection("SC").Path); + sc = temp11; } char c = 'q'; - if (TryGetConfigurationValue(configuration, key: "C", out string? value7) && value7 is not null) + if (TryGetConfigurationValue(configuration, key: "C", out string? value12) && value12 is not null && TryParseChar(value12, configuration.GetSection("C").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp13)) { - c = ParseChar(value7, configuration.GetSection("C").Path); + c = temp13; } int? nage = (int?)(42); - if (TryGetConfigurationValue(configuration, key: "NAge", out string? value8)) + if (TryGetConfigurationValue(configuration, key: "NAge", out string? value14)) { - if (string.IsNullOrEmpty(value8)) + if (string.IsNullOrEmpty(value14)) { nage = (int?)(42); } else { - nage = ParseInt(value8, configuration.GetSection("NAge").Path); + if (TryParseInt(value14, configuration.GetSection("NAge").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp15)) + { + nage = temp15; + } } } float? nf = 42F; - if (TryGetConfigurationValue(configuration, key: "NF", out string? value9)) + if (TryGetConfigurationValue(configuration, key: "NF", out string? value16)) { - if (string.IsNullOrEmpty(value9)) + if (string.IsNullOrEmpty(value16)) { nf = 42F; } else { - nf = ParseFloat(value9, configuration.GetSection("NF").Path); + if (TryParseFloat(value16, configuration.GetSection("NF").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp17)) + { + nf = temp17; + } } } double? nd = 3.1415899999999999D; - if (TryGetConfigurationValue(configuration, key: "ND", out string? value10)) + if (TryGetConfigurationValue(configuration, key: "ND", out string? value18)) { - if (string.IsNullOrEmpty(value10)) + if (string.IsNullOrEmpty(value18)) { nd = 3.1415899999999999D; } else { - nd = ParseDouble(value10, configuration.GetSection("ND").Path); + if (TryParseDouble(value18, configuration.GetSection("ND").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp19)) + { + nd = temp19; + } } } decimal? nm = 3.1415926535897932384626433M; - if (TryGetConfigurationValue(configuration, key: "NM", out string? value11)) + if (TryGetConfigurationValue(configuration, key: "NM", out string? value20)) { - if (string.IsNullOrEmpty(value11)) + if (string.IsNullOrEmpty(value20)) { nm = 3.1415926535897932384626433M; } else { - nm = ParseDecimal(value11, configuration.GetSection("NM").Path); + if (TryParseDecimal(value20, configuration.GetSection("NM").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp21)) + { + nm = temp21; + } } } global::System.StringComparison? nsc = (global::System.StringComparison?)(4); - if (TryGetConfigurationValue(configuration, key: "NSC", out string? value12)) + if (TryGetConfigurationValue(configuration, key: "NSC", out string? value22)) { - if (string.IsNullOrEmpty(value12)) + if (string.IsNullOrEmpty(value22)) { nsc = (global::System.StringComparison?)(4); } else { - nsc = ParseEnum(value12, configuration.GetSection("NSC").Path); + if (TryParseEnum(value22, configuration.GetSection("NSC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.StringComparison temp23)) + { + nsc = temp23; + } } } char? nc = 'q'; - if (TryGetConfigurationValue(configuration, key: "NC", out string? value13)) + if (TryGetConfigurationValue(configuration, key: "NC", out string? value24)) { - if (string.IsNullOrEmpty(value13)) + if (string.IsNullOrEmpty(value24)) { nc = 'q'; } else { - nc = ParseChar(value13, configuration.GetSection("NC").Path); + if (TryParseChar(value24, configuration.GetSection("NC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp25)) + { + nc = temp25; + } } } @@ -241,11 +259,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, string? path) where T : struct + public static bool TryParseEnum(string value, string? path, bool errorOnFailedBinding, out T result) where T : struct { try { - return (T)Enum.Parse(typeof(T), value, ignoreCase: true); + result = (T)Enum.Parse(typeof(T), value, ignoreCase: true); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -253,11 +277,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -265,11 +295,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -277,11 +313,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -289,11 +331,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static decimal ParseDecimal(string value, string? path) + public static bool TryParseDecimal(string value, string? path, bool errorOnFailedBinding, out decimal result) { try { - return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -301,11 +349,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static char ParseChar(string value, string? path) + public static bool TryParseChar(string value, string? path, bool errorOnFailedBinding, out char result) { try { - return char.Parse(value); + result = char.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/Primitives.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/Primitives.generated.txt index c04c278e695ee9..e9f61bb12e1309 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/Primitives.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/Primitives.generated.txt @@ -62,9 +62,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "Prop0", out string? value0)) { - if (!string.IsNullOrEmpty(value0)) + if (!string.IsNullOrEmpty(value0) && TryParseBool(value0, configuration.GetSection("Prop0").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out bool temp1)) { - instance.Prop0 = ParseBool(value0, configuration.GetSection("Prop0").Path); + instance.Prop0 = temp1; } } else if (defaultValueIfNotFound) @@ -72,11 +72,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop0 = instance.Prop0; } - if (TryGetConfigurationValue(configuration, key: "Prop1", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "Prop1", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseByte(value2, configuration.GetSection("Prop1").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte temp3)) { - instance.Prop1 = ParseByte(value1, configuration.GetSection("Prop1").Path); + instance.Prop1 = temp3; } } else if (defaultValueIfNotFound) @@ -84,11 +84,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop1 = instance.Prop1; } - if (TryGetConfigurationValue(configuration, key: "Prop2", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "Prop2", out string? value4)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value4) && TryParseSbyte(value4, configuration.GetSection("Prop2").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out sbyte temp5)) { - instance.Prop2 = ParseSbyte(value2, configuration.GetSection("Prop2").Path); + instance.Prop2 = temp5; } } else if (defaultValueIfNotFound) @@ -96,11 +96,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop2 = instance.Prop2; } - if (TryGetConfigurationValue(configuration, key: "Prop3", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "Prop3", out string? value6)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value6) && TryParseChar(value6, configuration.GetSection("Prop3").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp7)) { - instance.Prop3 = ParseChar(value3, configuration.GetSection("Prop3").Path); + instance.Prop3 = temp7; } } else if (defaultValueIfNotFound) @@ -108,11 +108,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop3 = instance.Prop3; } - if (TryGetConfigurationValue(configuration, key: "Prop4", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "Prop4", out string? value8)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value8) && TryParseDouble(value8, configuration.GetSection("Prop4").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp9)) { - instance.Prop4 = ParseDouble(value4, configuration.GetSection("Prop4").Path); + instance.Prop4 = temp9; } } else if (defaultValueIfNotFound) @@ -120,9 +120,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop4 = instance.Prop4; } - if (TryGetConfigurationValue(configuration, key: "Prop5", out string? value5)) + if (TryGetConfigurationValue(configuration, key: "Prop5", out string? value10)) { - instance.Prop5 = value5; + instance.Prop5 = value10; } else if (defaultValueIfNotFound) { @@ -133,11 +133,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop6", out string? value6)) + if (TryGetConfigurationValue(configuration, key: "Prop6", out string? value11)) { - if (!string.IsNullOrEmpty(value6)) + if (!string.IsNullOrEmpty(value11) && TryParseInt(value11, configuration.GetSection("Prop6").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp12)) { - instance.Prop6 = ParseInt(value6, configuration.GetSection("Prop6").Path); + instance.Prop6 = temp12; } } else if (defaultValueIfNotFound) @@ -145,11 +145,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop6 = instance.Prop6; } - if (TryGetConfigurationValue(configuration, key: "Prop8", out string? value7)) + if (TryGetConfigurationValue(configuration, key: "Prop8", out string? value13)) { - if (!string.IsNullOrEmpty(value7)) + if (!string.IsNullOrEmpty(value13) && TryParseShort(value13, configuration.GetSection("Prop8").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out short temp14)) { - instance.Prop8 = ParseShort(value7, configuration.GetSection("Prop8").Path); + instance.Prop8 = temp14; } } else if (defaultValueIfNotFound) @@ -157,11 +157,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop8 = instance.Prop8; } - if (TryGetConfigurationValue(configuration, key: "Prop9", out string? value8)) + if (TryGetConfigurationValue(configuration, key: "Prop9", out string? value15)) { - if (!string.IsNullOrEmpty(value8)) + if (!string.IsNullOrEmpty(value15) && TryParseLong(value15, configuration.GetSection("Prop9").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out long temp16)) { - instance.Prop9 = ParseLong(value8, configuration.GetSection("Prop9").Path); + instance.Prop9 = temp16; } } else if (defaultValueIfNotFound) @@ -169,11 +169,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop9 = instance.Prop9; } - if (TryGetConfigurationValue(configuration, key: "Prop10", out string? value9)) + if (TryGetConfigurationValue(configuration, key: "Prop10", out string? value17)) { - if (!string.IsNullOrEmpty(value9)) + if (!string.IsNullOrEmpty(value17) && TryParseFloat(value17, configuration.GetSection("Prop10").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp18)) { - instance.Prop10 = ParseFloat(value9, configuration.GetSection("Prop10").Path); + instance.Prop10 = temp18; } } else if (defaultValueIfNotFound) @@ -181,11 +181,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop10 = instance.Prop10; } - if (TryGetConfigurationValue(configuration, key: "Prop13", out string? value10)) + if (TryGetConfigurationValue(configuration, key: "Prop13", out string? value19)) { - if (!string.IsNullOrEmpty(value10)) + if (!string.IsNullOrEmpty(value19) && TryParseUshort(value19, configuration.GetSection("Prop13").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out ushort temp20)) { - instance.Prop13 = ParseUshort(value10, configuration.GetSection("Prop13").Path); + instance.Prop13 = temp20; } } else if (defaultValueIfNotFound) @@ -193,11 +193,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop13 = instance.Prop13; } - if (TryGetConfigurationValue(configuration, key: "Prop14", out string? value11)) + if (TryGetConfigurationValue(configuration, key: "Prop14", out string? value21)) { - if (!string.IsNullOrEmpty(value11)) + if (!string.IsNullOrEmpty(value21) && TryParseUint(value21, configuration.GetSection("Prop14").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out uint temp22)) { - instance.Prop14 = ParseUint(value11, configuration.GetSection("Prop14").Path); + instance.Prop14 = temp22; } } else if (defaultValueIfNotFound) @@ -205,11 +205,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop14 = instance.Prop14; } - if (TryGetConfigurationValue(configuration, key: "Prop15", out string? value12)) + if (TryGetConfigurationValue(configuration, key: "Prop15", out string? value23)) { - if (!string.IsNullOrEmpty(value12)) + if (!string.IsNullOrEmpty(value23) && TryParseUlong(value23, configuration.GetSection("Prop15").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out ulong temp24)) { - instance.Prop15 = ParseUlong(value12, configuration.GetSection("Prop15").Path); + instance.Prop15 = temp24; } } else if (defaultValueIfNotFound) @@ -217,9 +217,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop15 = instance.Prop15; } - if (TryGetConfigurationValue(configuration, key: "Prop16", out string? value13)) + if (TryGetConfigurationValue(configuration, key: "Prop16", out string? value25)) { - instance.Prop16 = value13; + instance.Prop16 = value25; } else if (defaultValueIfNotFound) { @@ -230,17 +230,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop17", out string? value14)) + if (TryGetConfigurationValue(configuration, key: "Prop17", out string? value26)) { - if (value14 is null) + if (value26 is null) { instance.Prop17 = null; } else { - if (!string.IsNullOrEmpty(value14)) + if (!string.IsNullOrEmpty(value26) && TryParseSystemGlobalizationCultureInfo(value26, configuration.GetSection("Prop17").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Globalization.CultureInfo temp27)) { - instance.Prop17 = ParseSystemGlobalizationCultureInfo(value14, configuration.GetSection("Prop17").Path); + instance.Prop17 = temp27; } } } @@ -253,11 +253,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop19", out string? value15)) + if (TryGetConfigurationValue(configuration, key: "Prop19", out string? value28)) { - if (!string.IsNullOrEmpty(value15)) + if (!string.IsNullOrEmpty(value28) && TryParseSystemDateTime(value28, configuration.GetSection("Prop19").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTime temp29)) { - instance.Prop19 = ParseSystemDateTime(value15, configuration.GetSection("Prop19").Path); + instance.Prop19 = temp29; } } else if (defaultValueIfNotFound) @@ -265,11 +265,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop19 = instance.Prop19; } - if (TryGetConfigurationValue(configuration, key: "Prop20", out string? value16)) + if (TryGetConfigurationValue(configuration, key: "Prop20", out string? value30)) { - if (!string.IsNullOrEmpty(value16)) + if (!string.IsNullOrEmpty(value30) && TryParseSystemDateTimeOffset(value30, configuration.GetSection("Prop20").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTimeOffset temp31)) { - instance.Prop20 = ParseSystemDateTimeOffset(value16, configuration.GetSection("Prop20").Path); + instance.Prop20 = temp31; } } else if (defaultValueIfNotFound) @@ -277,11 +277,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop20 = instance.Prop20; } - if (TryGetConfigurationValue(configuration, key: "Prop21", out string? value17)) + if (TryGetConfigurationValue(configuration, key: "Prop21", out string? value32)) { - if (!string.IsNullOrEmpty(value17)) + if (!string.IsNullOrEmpty(value32) && TryParseDecimal(value32, configuration.GetSection("Prop21").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp33)) { - instance.Prop21 = ParseDecimal(value17, configuration.GetSection("Prop21").Path); + instance.Prop21 = temp33; } } else if (defaultValueIfNotFound) @@ -289,11 +289,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop21 = instance.Prop21; } - if (TryGetConfigurationValue(configuration, key: "Prop23", out string? value18)) + if (TryGetConfigurationValue(configuration, key: "Prop23", out string? value34)) { - if (!string.IsNullOrEmpty(value18)) + if (!string.IsNullOrEmpty(value34) && TryParseSystemTimeSpan(value34, configuration.GetSection("Prop23").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.TimeSpan temp35)) { - instance.Prop23 = ParseSystemTimeSpan(value18, configuration.GetSection("Prop23").Path); + instance.Prop23 = temp35; } } else if (defaultValueIfNotFound) @@ -301,11 +301,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop23 = instance.Prop23; } - if (TryGetConfigurationValue(configuration, key: "Prop24", out string? value19)) + if (TryGetConfigurationValue(configuration, key: "Prop24", out string? value36)) { - if (!string.IsNullOrEmpty(value19)) + if (!string.IsNullOrEmpty(value36) && TryParseSystemGuid(value36, configuration.GetSection("Prop24").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Guid temp37)) { - instance.Prop24 = ParseSystemGuid(value19, configuration.GetSection("Prop24").Path); + instance.Prop24 = temp37; } } else if (defaultValueIfNotFound) @@ -313,17 +313,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop24 = instance.Prop24; } - if (TryGetConfigurationValue(configuration, key: "Prop25", out string? value20)) + if (TryGetConfigurationValue(configuration, key: "Prop25", out string? value38)) { - if (value20 is null) + if (value38 is null) { instance.Prop25 = null; } else { - if (!string.IsNullOrEmpty(value20)) + if (!string.IsNullOrEmpty(value38) && TryParseSystemUri(value38, configuration.GetSection("Prop25").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Uri temp39)) { - instance.Prop25 = ParseSystemUri(value20, configuration.GetSection("Prop25").Path); + instance.Prop25 = temp39; } } } @@ -336,17 +336,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop26", out string? value21)) + if (TryGetConfigurationValue(configuration, key: "Prop26", out string? value40)) { - if (value21 is null) + if (value40 is null) { instance.Prop26 = null; } else { - if (!string.IsNullOrEmpty(value21)) + if (!string.IsNullOrEmpty(value40) && TryParseSystemVersion(value40, configuration.GetSection("Prop26").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Version temp41)) { - instance.Prop26 = ParseSystemVersion(value21, configuration.GetSection("Prop26").Path); + instance.Prop26 = temp41; } } } @@ -359,11 +359,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop27", out string? value22)) + if (TryGetConfigurationValue(configuration, key: "Prop27", out string? value42)) { - if (!string.IsNullOrEmpty(value22)) + if (!string.IsNullOrEmpty(value42) && TryParseEnum(value42, configuration.GetSection("Prop27").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DayOfWeek temp43)) { - instance.Prop27 = ParseEnum(value22, configuration.GetSection("Prop27").Path); + instance.Prop27 = temp43; } } else if (defaultValueIfNotFound) @@ -371,21 +371,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop27 = instance.Prop27; } - if (TryGetConfigurationValue(configuration, key: "Prop28", out string? value23)) + if (TryGetConfigurationValue(configuration, key: "Prop28", out string? value44)) { - if (value23 is null) + if (value44 is null) { instance.Prop28 = null; } else { - if (value23 == string.Empty) + if (value44 == string.Empty && TryParseByteArray(value44, configuration.GetSection("Prop28").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte[] temp45)) { - instance.Prop28 = ParseByteArray(value23, configuration.GetSection("Prop28").Path); + instance.Prop28 = temp45; } - else if (!string.IsNullOrEmpty(value23)) + else if (!string.IsNullOrEmpty(value44) && TryParseByteArray(value44, configuration.GetSection("Prop28").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte[] temp46)) { - instance.Prop28 = ParseByteArray(value23, configuration.GetSection("Prop28").Path); + instance.Prop28 = temp46; } } } @@ -398,11 +398,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop29", out string? value24)) + if (TryGetConfigurationValue(configuration, key: "Prop29", out string? value47)) { - if (!string.IsNullOrEmpty(value24)) + if (!string.IsNullOrEmpty(value47) && TryParseInt(value47, configuration.GetSection("Prop29").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp48)) { - instance.Prop29 = ParseInt(value24, configuration.GetSection("Prop29").Path); + instance.Prop29 = temp48; } } else if (defaultValueIfNotFound) @@ -410,11 +410,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop29 = instance.Prop29; } - if (TryGetConfigurationValue(configuration, key: "Prop30", out string? value25)) + if (TryGetConfigurationValue(configuration, key: "Prop30", out string? value49)) { - if (!string.IsNullOrEmpty(value25)) + if (!string.IsNullOrEmpty(value49) && TryParseSystemDateTime(value49, configuration.GetSection("Prop30").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTime temp50)) { - instance.Prop30 = ParseSystemDateTime(value25, configuration.GetSection("Prop30").Path); + instance.Prop30 = temp50; } } else if (defaultValueIfNotFound) @@ -458,11 +458,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, string? path) where T : struct + public static bool TryParseEnum(string value, string? path, bool errorOnFailedBinding, out T result) where T : struct { try { - return (T)Enum.Parse(typeof(T), value, ignoreCase: true); + result = (T)Enum.Parse(typeof(T), value, ignoreCase: true); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -470,11 +476,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -482,11 +494,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static byte ParseByte(string value, string? path) + public static bool TryParseByte(string value, string? path, bool errorOnFailedBinding, out byte result) { try { - return byte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = byte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -494,11 +512,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static sbyte ParseSbyte(string value, string? path) + public static bool TryParseSbyte(string value, string? path, bool errorOnFailedBinding, out sbyte result) { try { - return sbyte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = sbyte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -506,11 +530,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static char ParseChar(string value, string? path) + public static bool TryParseChar(string value, string? path, bool errorOnFailedBinding, out char result) { try { - return char.Parse(value); + result = char.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -518,11 +548,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -530,11 +566,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -542,11 +584,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static short ParseShort(string value, string? path) + public static bool TryParseShort(string value, string? path, bool errorOnFailedBinding, out short result) { try { - return short.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = short.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -554,11 +602,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static long ParseLong(string value, string? path) + public static bool TryParseLong(string value, string? path, bool errorOnFailedBinding, out long result) { try { - return long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -566,11 +620,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -578,11 +638,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static ushort ParseUshort(string value, string? path) + public static bool TryParseUshort(string value, string? path, bool errorOnFailedBinding, out ushort result) { try { - return ushort.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = ushort.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -590,11 +656,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static uint ParseUint(string value, string? path) + public static bool TryParseUint(string value, string? path, bool errorOnFailedBinding, out uint result) { try { - return uint.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = uint.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -602,11 +674,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static ulong ParseUlong(string value, string? path) + public static bool TryParseUlong(string value, string? path, bool errorOnFailedBinding, out ulong result) { try { - return ulong.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = ulong.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -614,11 +692,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -626,11 +710,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.DateTime ParseSystemDateTime(string value, string? path) + public static bool TryParseSystemDateTime(string value, string? path, bool errorOnFailedBinding, out global::System.DateTime result) { try { - return global::System.DateTime.Parse(value, CultureInfo.InvariantCulture); + result = global::System.DateTime.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -638,11 +728,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.DateTimeOffset ParseSystemDateTimeOffset(string value, string? path) + public static bool TryParseSystemDateTimeOffset(string value, string? path, bool errorOnFailedBinding, out global::System.DateTimeOffset result) { try { - return global::System.DateTimeOffset.Parse(value, CultureInfo.InvariantCulture); + result = global::System.DateTimeOffset.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -650,11 +746,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static decimal ParseDecimal(string value, string? path) + public static bool TryParseDecimal(string value, string? path, bool errorOnFailedBinding, out decimal result) { try { - return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -662,11 +764,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.TimeSpan ParseSystemTimeSpan(string value, string? path) + public static bool TryParseSystemTimeSpan(string value, string? path, bool errorOnFailedBinding, out global::System.TimeSpan result) { try { - return global::System.TimeSpan.Parse(value, CultureInfo.InvariantCulture); + result = global::System.TimeSpan.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -674,11 +782,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Guid ParseSystemGuid(string value, string? path) + public static bool TryParseSystemGuid(string value, string? path, bool errorOnFailedBinding, out global::System.Guid result) { try { - return global::System.Guid.Parse(value); + result = global::System.Guid.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -686,11 +800,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Uri ParseSystemUri(string value, string? path) + public static bool TryParseSystemUri(string value, string? path, bool errorOnFailedBinding, out global::System.Uri result) { try { - return new Uri(value, UriKind.RelativeOrAbsolute); + result = new Uri(value, UriKind.RelativeOrAbsolute); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -698,11 +818,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Version ParseSystemVersion(string value, string? path) + public static bool TryParseSystemVersion(string value, string? path, bool errorOnFailedBinding, out global::System.Version result) { try { - return global::System.Version.Parse(value); + result = global::System.Version.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -710,11 +836,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static byte[] ParseByteArray(string value, string? path) + public static bool TryParseByteArray(string value, string? path, bool errorOnFailedBinding, out byte[] result) { try { - return Convert.FromBase64String(value); + result = Convert.FromBase64String(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/UnsupportedTypes.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/UnsupportedTypes.generated.txt index 57ebb4a3cdc268..395c7d67312343 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/UnsupportedTypes.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/net462/Version1/UnsupportedTypes.generated.txt @@ -145,9 +145,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "Age", out string? value3)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("Age").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.Age = ParseInt(value3, configuration.GetSection("Age").Path); + instance.Age = temp4; } } else if (defaultValueIfNotFound) @@ -155,43 +155,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Age = instance.Age; } - var value4 = configuration.GetSection("List"); - if (AsConfigWithChildren(value4) is IConfigurationSection section5) + var value5 = configuration.GetSection("List"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp7 = instance.List; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.List = temp7; + global::System.Collections.Generic.List? temp8 = instance.List; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.List = temp8; } else { instance.List = instance.List; } - var value8 = configuration.GetSection("Array"); - if (AsConfigWithChildren(value8) is IConfigurationSection section9) + var value9 = configuration.GetSection("Array"); + if (AsConfigWithChildren(value9) is IConfigurationSection section10) { - string[]? temp11 = instance.Array; - temp11 ??= new string[0]; - BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); - instance.Array = temp11; + string[]? temp12 = instance.Array; + temp12 ??= new string[0]; + BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); + instance.Array = temp12; } else { instance.Array = instance.Array; } - if (instance.Array is null && TryGetConfigurationValue(value8, key: null, out string? value12) && value12 == string.Empty) + if (instance.Array is null && TryGetConfigurationValue(value9, key: null, out string? value13) && value13 == string.Empty) { instance.Array = global::System.Array.Empty(); } - var value13 = configuration.GetSection("Record"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value14 = configuration.GetSection("Record"); + if (AsConfigWithChildren(value14) is IConfigurationSection section15) { - global::Record? temp16 = instance.Record; - temp16 ??= InitializeRecord___System__Action___(section14, binderOptions); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.Record = temp16; + global::Record? temp17 = instance.Record; + temp17 ??= InitializeRecord___System__Action___(section15, binderOptions); + BindCore(section15, ref temp17, defaultValueIfNotFound: false, binderOptions); + instance.Record = temp17; } else { @@ -202,9 +202,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static global::Record InitializeRecord___System__Action___(IConfiguration configuration, BinderOptions? binderOptions) { int x = (int)(10); - if (TryGetConfigurationValue(configuration, key: "x", out string? value17) && value17 is not null) + if (TryGetConfigurationValue(configuration, key: "x", out string? value18) && value18 is not null && TryParseInt(value18, configuration.GetSection("x").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp19)) { - x = ParseInt(value17, configuration.GetSection("x").Path); + x = temp19; } return new global::Record(x) @@ -284,11 +284,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind.generated.txt index 87feac647752d1..55ef28a454ef98 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind.generated.txt @@ -81,7 +81,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { @@ -89,9 +89,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -124,9 +124,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -137,11 +137,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -149,39 +149,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -203,17 +203,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -251,11 +251,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Instance.generated.txt index e0815e028e0bbb..03b7c9546dc1ac 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Instance.generated.txt @@ -51,7 +51,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { @@ -59,9 +59,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -107,11 +107,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -119,39 +119,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -173,17 +173,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -203,11 +203,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Instance_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Instance_BinderOptions.generated.txt index 33fd5e64aec9dc..5f49ea5c73bb86 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Instance_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Instance_BinderOptions.generated.txt @@ -51,7 +51,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { @@ -59,9 +59,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -107,11 +107,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -119,39 +119,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -173,17 +173,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -221,11 +221,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Key_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Key_Instance.generated.txt index ab10fc8da72e6f..b79fdc3a9750e5 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Key_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Bind_Key_Instance.generated.txt @@ -51,7 +51,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyDictionary", "MyComplexDictionary" }); public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.List instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { @@ -59,9 +59,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -107,11 +107,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -119,39 +119,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -173,17 +173,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -203,11 +203,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get.generated.txt index be7a0e7634f74c..163c6a0b879f84 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get.generated.txt @@ -52,8 +52,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); - private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -88,9 +88,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp2); } } } @@ -98,22 +98,22 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp2 = new List(); + var temp3 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - temp2.Add(ParseInt(value, section.Path)); + temp3.Add(temp4); } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp2.Count); - temp2.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp3.Count); + temp3.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) @@ -131,9 +131,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -144,11 +144,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -156,43 +156,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyArray"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - int[]? temp12 = instance.MyArray; - temp12 ??= new int[0]; - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp12; + int[]? temp15 = instance.MyArray; + temp15 ??= new int[0]; + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp15; } else { instance.MyArray = instance.MyArray; } - if (instance.MyArray is null && TryGetConfigurationValue(value9, key: null, out string? value13) && value13 == string.Empty) + if (instance.MyArray is null && TryGetConfigurationValue(value12, key: null, out string? value16) && value16 == string.Empty) { instance.MyArray = global::System.Array.Empty(); } - var value14 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value14) is IConfigurationSection section15) + var value17 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value17) is IConfigurationSection section18) { - global::System.Collections.Generic.Dictionary? temp17 = instance.MyDictionary; - temp17 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section15, ref temp17, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp17; + global::System.Collections.Generic.Dictionary? temp20 = instance.MyDictionary; + temp20 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section18, ref temp20, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp20; } else { @@ -204,11 +204,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value18)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value21)) { - if (!string.IsNullOrEmpty(value18)) + if (!string.IsNullOrEmpty(value21) && TryParseInt(value21, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp22)) { - instance.MyInt = ParseInt(value18, configuration.GetSection("MyInt").Path); + instance.MyInt = temp22; } } else if (defaultValueIfNotFound) @@ -231,17 +231,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -288,11 +288,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue.generated.txt index e1df44947a953f..5932f818e860e8 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue.generated.txt @@ -63,19 +63,31 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(int)) { - return ParseInt(value, section.Path); + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } } else if (type == typeof(bool?)) { - return ParseBool(value, section.Path); + if (TryParseBool(value, section.Path, true, out bool temp1)) + { + return temp1; + } } else if (type == typeof(byte[])) { - return ParseByteArray(value, section.Path); + if (TryParseByteArray(value, section.Path, true, out byte[] temp2)) + { + return temp2; + } } else if (type == typeof(global::System.Globalization.CultureInfo)) { - return ParseSystemGlobalizationCultureInfo(value, section.Path); + if (TryParseSystemGlobalizationCultureInfo(value, section.Path, true, out global::System.Globalization.CultureInfo temp3)) + { + return temp3; + } } } @@ -94,11 +106,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -106,11 +124,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -118,11 +142,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static byte[] ParseByteArray(string value, string? path) + public static bool TryParseByteArray(string value, string? path, bool errorOnFailedBinding, out byte[] result) { try { - return Convert.FromBase64String(value); + result = Convert.FromBase64String(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -130,11 +160,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_T_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_T_Key.generated.txt index 4d77e3b10b4f79..bf24b6f0fe4f6f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_T_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_T_Key.generated.txt @@ -49,7 +49,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(int)) { - return ParseInt(value, section.Path); + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } } } @@ -68,11 +71,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_T_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_T_Key_DefaultValue.generated.txt index b40de2a70b30c1..9b5fa305598e74 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_T_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_T_Key_DefaultValue.generated.txt @@ -50,7 +50,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(int)) { - return ParseInt(value, section.Path); + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } } } @@ -69,11 +72,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_TypeOf_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_TypeOf_Key.generated.txt index 5f8fe175e58134..09b2b0dd5390eb 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_TypeOf_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_TypeOf_Key.generated.txt @@ -49,7 +49,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(bool?)) { - return ParseBool(value, section.Path); + if (TryParseBool(value, section.Path, true, out bool temp0)) + { + return temp0; + } } } @@ -68,11 +71,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_TypeOf_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_TypeOf_Key_DefaultValue.generated.txt index 25b3bf8c5f1ea8..3c1e31b92f2278 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_TypeOf_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/GetValue_TypeOf_Key_DefaultValue.generated.txt @@ -50,7 +50,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(global::System.Globalization.CultureInfo)) { - return ParseSystemGlobalizationCultureInfo(value, section.Path); + if (TryParseSystemGlobalizationCultureInfo(value, section.Path, true, out global::System.Globalization.CultureInfo temp0)) + { + return temp0; + } } } @@ -69,11 +72,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_PrimitivesOnly.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_PrimitivesOnly.generated.txt index 7240e335809319..c02422b07cd02c 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_PrimitivesOnly.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_PrimitivesOnly.generated.txt @@ -70,11 +70,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - return ParseInt(value, section.Path); + return temp0; } } + return null; } else if (type == typeof(string)) { @@ -95,11 +96,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseFloat(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp1)) { - return ParseFloat(value, section.Path); + return temp1; } } + return null; } else if (type == typeof(double)) { @@ -109,11 +111,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseDouble(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp2)) { - return ParseDouble(value, section.Path); + return temp2; } } + return null; } throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input."); @@ -167,11 +170,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -179,11 +188,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -191,11 +206,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_T.generated.txt index f9bf7389f135f2..0993e7adc565ee 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_T.generated.txt @@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -69,9 +69,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -79,22 +79,22 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp1 = new List(); + var temp2 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - temp1.Add(ParseInt(value, section.Path)); + temp2.Add(temp3); } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp1.Count); - temp1.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp2.Count); + temp2.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) @@ -112,9 +112,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value4)) { - instance.MyString = value2; + instance.MyString = value4; } else if (defaultValueIfNotFound) { @@ -125,11 +125,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value5)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value5) && TryParseInt(value5, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp6)) { - instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); + instance.MyInt = temp6; } } else if (defaultValueIfNotFound) @@ -137,43 +137,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value4 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value4) is IConfigurationSection section5) + var value7 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value7) is IConfigurationSection section8) { - global::System.Collections.Generic.List? temp7 = instance.MyList; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp7; + global::System.Collections.Generic.List? temp10 = instance.MyList; + temp10 ??= new global::System.Collections.Generic.List(); + BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp10; } else { instance.MyList = instance.MyList; } - var value8 = configuration.GetSection("MyArray"); - if (AsConfigWithChildren(value8) is IConfigurationSection section9) + var value11 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value11) is IConfigurationSection section12) { - int[]? temp11 = instance.MyArray; - temp11 ??= new int[0]; - BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp11; + int[]? temp14 = instance.MyArray; + temp14 ??= new int[0]; + BindCore(section12, ref temp14, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp14; } else { instance.MyArray = instance.MyArray; } - if (instance.MyArray is null && TryGetConfigurationValue(value8, key: null, out string? value12) && value12 == string.Empty) + if (instance.MyArray is null && TryGetConfigurationValue(value11, key: null, out string? value15) && value15 == string.Empty) { instance.MyArray = global::System.Array.Empty(); } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -195,17 +195,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -252,11 +252,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_T_BinderOptions.generated.txt index ade47696525835..51f9250db46fa3 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_T_BinderOptions.generated.txt @@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyArray", "MyDictionary" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -69,9 +69,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -79,22 +79,22 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp1 = new List(); + var temp2 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - temp1.Add(ParseInt(value, section.Path)); + temp2.Add(temp3); } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp1.Count); - temp1.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp2.Count); + temp2.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) @@ -112,9 +112,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value4)) { - instance.MyString = value2; + instance.MyString = value4; } else if (defaultValueIfNotFound) { @@ -125,11 +125,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value5)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value5) && TryParseInt(value5, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp6)) { - instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); + instance.MyInt = temp6; } } else if (defaultValueIfNotFound) @@ -137,43 +137,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value4 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value4) is IConfigurationSection section5) + var value7 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value7) is IConfigurationSection section8) { - global::System.Collections.Generic.List? temp7 = instance.MyList; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp7; + global::System.Collections.Generic.List? temp10 = instance.MyList; + temp10 ??= new global::System.Collections.Generic.List(); + BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp10; } else { instance.MyList = instance.MyList; } - var value8 = configuration.GetSection("MyArray"); - if (AsConfigWithChildren(value8) is IConfigurationSection section9) + var value11 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value11) is IConfigurationSection section12) { - int[]? temp11 = instance.MyArray; - temp11 ??= new int[0]; - BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp11; + int[]? temp14 = instance.MyArray; + temp14 ??= new int[0]; + BindCore(section12, ref temp14, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp14; } else { instance.MyArray = instance.MyArray; } - if (instance.MyArray is null && TryGetConfigurationValue(value8, key: null, out string? value12) && value12 == string.Empty) + if (instance.MyArray is null && TryGetConfigurationValue(value11, key: null, out string? value15) && value15 == string.Empty) { instance.MyArray = global::System.Array.Empty(); } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -195,17 +195,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -252,11 +252,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_TypeOf.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_TypeOf.generated.txt index 64fad76a87b3c9..0dce3911859bdb 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_TypeOf.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_TypeOf.generated.txt @@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -69,9 +69,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value1) && TryParseInt(value1, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp2; } } else if (defaultValueIfNotFound) @@ -94,17 +94,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -151,11 +151,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_TypeOf_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_TypeOf_BinderOptions.generated.txt index 4249131566df11..2efdbda376044f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_TypeOf_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version0/Get_TypeOf_BinderOptions.generated.txt @@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -69,9 +69,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value1) && TryParseInt(value1, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp2; } } else if (defaultValueIfNotFound) @@ -94,17 +94,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -151,11 +151,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind.generated.txt index 7f4fd63b274009..dac79bb94876df 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind.generated.txt @@ -89,9 +89,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -124,9 +124,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -137,11 +137,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -149,39 +149,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -251,11 +251,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Instance.generated.txt index 60a5eb1103e120..d174a3ac4323dd 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Instance.generated.txt @@ -59,9 +59,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -107,11 +107,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -119,39 +119,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -203,11 +203,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Instance_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Instance_BinderOptions.generated.txt index fcd3c5465d9021..6268e7c2766340 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Instance_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Instance_BinderOptions.generated.txt @@ -59,9 +59,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -107,11 +107,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -119,39 +119,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -221,11 +221,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Key_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Key_Instance.generated.txt index 88c3f160a93ba6..9013f8aa66a768 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Key_Instance.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Bind_Key_Instance.generated.txt @@ -59,9 +59,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp0); } } } @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value0)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) { - instance.MyString = value0; + instance.MyString = value1; } else if (defaultValueIfNotFound) { @@ -107,11 +107,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -119,39 +119,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value2 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value2) is IConfigurationSection section3) + var value4 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::System.Collections.Generic.List? temp5 = instance.MyList; - temp5 ??= new global::System.Collections.Generic.List(); - BindCore(section3, ref temp5, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp5; + global::System.Collections.Generic.List? temp7 = instance.MyList; + temp7 ??= new global::System.Collections.Generic.List(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp7; } else { instance.MyList = instance.MyList; } - var value6 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value6) is IConfigurationSection section7) + var value8 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.Dictionary? temp9 = instance.MyDictionary; - temp9 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section7, ref temp9, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp9; + global::System.Collections.Generic.Dictionary? temp11 = instance.MyDictionary; + temp11 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp11; } else { instance.MyDictionary = instance.MyDictionary; } - var value10 = configuration.GetSection("MyComplexDictionary"); - if (AsConfigWithChildren(value10) is IConfigurationSection section11) + var value12 = configuration.GetSection("MyComplexDictionary"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.Dictionary? temp13 = instance.MyComplexDictionary; - temp13 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section11, ref temp13, defaultValueIfNotFound: false, binderOptions); - instance.MyComplexDictionary = temp13; + global::System.Collections.Generic.Dictionary? temp15 = instance.MyComplexDictionary; + temp15 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyComplexDictionary = temp15; } else { @@ -203,11 +203,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get.generated.txt index 99e17ad2ff8418..4256a69e26e9fd 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get.generated.txt @@ -88,9 +88,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp2); } } } @@ -98,22 +98,22 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp2 = new List(); + var temp3 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - temp2.Add(ParseInt(value, section.Path)); + temp3.Add(temp4); } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp2.Count); - temp2.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp3.Count); + temp3.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) @@ -131,9 +131,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -144,11 +144,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -156,43 +156,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyArray"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - int[]? temp12 = instance.MyArray; - temp12 ??= new int[0]; - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp12; + int[]? temp15 = instance.MyArray; + temp15 ??= new int[0]; + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp15; } else { instance.MyArray = instance.MyArray; } - if (instance.MyArray is null && TryGetConfigurationValue(value9, key: null, out string? value13) && value13 == string.Empty) + if (instance.MyArray is null && TryGetConfigurationValue(value12, key: null, out string? value16) && value16 == string.Empty) { instance.MyArray = global::System.Array.Empty(); } - var value14 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value14) is IConfigurationSection section15) + var value17 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value17) is IConfigurationSection section18) { - global::System.Collections.Generic.Dictionary? temp17 = instance.MyDictionary; - temp17 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section15, ref temp17, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp17; + global::System.Collections.Generic.Dictionary? temp20 = instance.MyDictionary; + temp20 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section18, ref temp20, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp20; } else { @@ -204,11 +204,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value18)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value21)) { - if (!string.IsNullOrEmpty(value18)) + if (!string.IsNullOrEmpty(value21) && TryParseInt(value21, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp22)) { - instance.MyInt = ParseInt(value18, configuration.GetSection("MyInt").Path); + instance.MyInt = temp22; } } else if (defaultValueIfNotFound) @@ -288,11 +288,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue.generated.txt index 5a5be508d1e0ca..5a9fd63177d340 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue.generated.txt @@ -63,19 +63,31 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(int)) { - return ParseInt(value, section.Path); + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } } else if (type == typeof(bool?)) { - return ParseBool(value, section.Path); + if (TryParseBool(value, section.Path, true, out bool temp1)) + { + return temp1; + } } else if (type == typeof(byte[])) { - return ParseByteArray(value, section.Path); + if (TryParseByteArray(value, section.Path, true, out byte[] temp2)) + { + return temp2; + } } else if (type == typeof(global::System.Globalization.CultureInfo)) { - return ParseSystemGlobalizationCultureInfo(value, section.Path); + if (TryParseSystemGlobalizationCultureInfo(value, section.Path, true, out global::System.Globalization.CultureInfo temp3)) + { + return temp3; + } } } @@ -94,11 +106,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -106,11 +124,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -118,11 +142,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static byte[] ParseByteArray(string value, string? path) + public static bool TryParseByteArray(string value, string? path, bool errorOnFailedBinding, out byte[] result) { try { - return Convert.FromBase64String(value); + result = Convert.FromBase64String(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -130,11 +160,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_T_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_T_Key.generated.txt index 048d17a875c909..27392ddb77b1be 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_T_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_T_Key.generated.txt @@ -49,7 +49,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(int)) { - return ParseInt(value, section.Path); + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } } } @@ -68,11 +71,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_T_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_T_Key_DefaultValue.generated.txt index e4afd9f3b5b285..929d61c83ce54b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_T_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_T_Key_DefaultValue.generated.txt @@ -50,7 +50,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(int)) { - return ParseInt(value, section.Path); + if (TryParseInt(value, section.Path, true, out int temp0)) + { + return temp0; + } } } @@ -69,11 +72,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_TypeOf_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_TypeOf_Key.generated.txt index aa906f8b1bce84..7f740e27b03f0b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_TypeOf_Key.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_TypeOf_Key.generated.txt @@ -49,7 +49,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(bool?)) { - return ParseBool(value, section.Path); + if (TryParseBool(value, section.Path, true, out bool temp0)) + { + return temp0; + } } } @@ -68,11 +71,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_TypeOf_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_TypeOf_Key_DefaultValue.generated.txt index 4b902228871eb8..dd3c468756fb49 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_TypeOf_Key_DefaultValue.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/GetValue_TypeOf_Key_DefaultValue.generated.txt @@ -50,7 +50,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (type == typeof(global::System.Globalization.CultureInfo)) { - return ParseSystemGlobalizationCultureInfo(value, section.Path); + if (TryParseSystemGlobalizationCultureInfo(value, section.Path, true, out global::System.Globalization.CultureInfo temp0)) + { + return temp0; + } } } @@ -69,11 +72,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return value != null; } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_PrimitivesOnly.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_PrimitivesOnly.generated.txt index 5dab04cdc700f8..c8f7227b53a223 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_PrimitivesOnly.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_PrimitivesOnly.generated.txt @@ -70,11 +70,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp0)) { - return ParseInt(value, section.Path); + return temp0; } } + return null; } else if (type == typeof(string)) { @@ -95,11 +96,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseFloat(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp1)) { - return ParseFloat(value, section.Path); + return temp1; } } + return null; } else if (type == typeof(double)) { @@ -109,11 +111,12 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } if (TryGetConfigurationValue(configuration, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseDouble(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp2)) { - return ParseDouble(value, section.Path); + return temp2; } } + return null; } throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input."); @@ -167,11 +170,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -179,11 +188,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -191,11 +206,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_T.generated.txt index 437bce7d135008..158ff250ec0bd7 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_T.generated.txt @@ -69,9 +69,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -79,22 +79,22 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp1 = new List(); + var temp2 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - temp1.Add(ParseInt(value, section.Path)); + temp2.Add(temp3); } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp1.Count); - temp1.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp2.Count); + temp2.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) @@ -112,9 +112,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value4)) { - instance.MyString = value2; + instance.MyString = value4; } else if (defaultValueIfNotFound) { @@ -125,11 +125,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value5)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value5) && TryParseInt(value5, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp6)) { - instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); + instance.MyInt = temp6; } } else if (defaultValueIfNotFound) @@ -137,43 +137,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value4 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value4) is IConfigurationSection section5) + var value7 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value7) is IConfigurationSection section8) { - global::System.Collections.Generic.List? temp7 = instance.MyList; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp7; + global::System.Collections.Generic.List? temp10 = instance.MyList; + temp10 ??= new global::System.Collections.Generic.List(); + BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp10; } else { instance.MyList = instance.MyList; } - var value8 = configuration.GetSection("MyArray"); - if (AsConfigWithChildren(value8) is IConfigurationSection section9) + var value11 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value11) is IConfigurationSection section12) { - int[]? temp11 = instance.MyArray; - temp11 ??= new int[0]; - BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp11; + int[]? temp14 = instance.MyArray; + temp14 ??= new int[0]; + BindCore(section12, ref temp14, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp14; } else { instance.MyArray = instance.MyArray; } - if (instance.MyArray is null && TryGetConfigurationValue(value8, key: null, out string? value12) && value12 == string.Empty) + if (instance.MyArray is null && TryGetConfigurationValue(value11, key: null, out string? value15) && value15 == string.Empty) { instance.MyArray = global::System.Array.Empty(); } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -252,11 +252,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_T_BinderOptions.generated.txt index 654d5d65e0192b..f006c2725aaff1 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_T_BinderOptions.generated.txt @@ -69,9 +69,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -79,22 +79,22 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref int[] instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - var temp1 = new List(); + var temp2 = new List(); foreach (IConfigurationSection section in configuration.GetChildren()) { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - temp1.Add(ParseInt(value, section.Path)); + temp2.Add(temp3); } } } int originalCount = instance.Length; - Array.Resize(ref instance, originalCount + temp1.Count); - temp1.CopyTo(instance, originalCount); + Array.Resize(ref instance, originalCount + temp2.Count); + temp2.CopyTo(instance, originalCount); } public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.Dictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) @@ -112,9 +112,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value4)) { - instance.MyString = value2; + instance.MyString = value4; } else if (defaultValueIfNotFound) { @@ -125,11 +125,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value5)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value5) && TryParseInt(value5, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp6)) { - instance.MyInt = ParseInt(value3, configuration.GetSection("MyInt").Path); + instance.MyInt = temp6; } } else if (defaultValueIfNotFound) @@ -137,43 +137,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value4 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value4) is IConfigurationSection section5) + var value7 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value7) is IConfigurationSection section8) { - global::System.Collections.Generic.List? temp7 = instance.MyList; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp7; + global::System.Collections.Generic.List? temp10 = instance.MyList; + temp10 ??= new global::System.Collections.Generic.List(); + BindCore(section8, ref temp10, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp10; } else { instance.MyList = instance.MyList; } - var value8 = configuration.GetSection("MyArray"); - if (AsConfigWithChildren(value8) is IConfigurationSection section9) + var value11 = configuration.GetSection("MyArray"); + if (AsConfigWithChildren(value11) is IConfigurationSection section12) { - int[]? temp11 = instance.MyArray; - temp11 ??= new int[0]; - BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); - instance.MyArray = temp11; + int[]? temp14 = instance.MyArray; + temp14 ??= new int[0]; + BindCore(section12, ref temp14, defaultValueIfNotFound: false, binderOptions); + instance.MyArray = temp14; } else { instance.MyArray = instance.MyArray; } - if (instance.MyArray is null && TryGetConfigurationValue(value8, key: null, out string? value12) && value12 == string.Empty) + if (instance.MyArray is null && TryGetConfigurationValue(value11, key: null, out string? value15) && value15 == string.Empty) { instance.MyArray = global::System.Array.Empty(); } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -252,11 +252,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_TypeOf.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_TypeOf.generated.txt index 08b582ec3f93d9..3247e10ef52e9a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_TypeOf.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_TypeOf.generated.txt @@ -69,9 +69,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value1) && TryParseInt(value1, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp2; } } else if (defaultValueIfNotFound) @@ -151,11 +151,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_TypeOf_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_TypeOf_BinderOptions.generated.txt index e7a5e8ac0194eb..988c8c6998931b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_TypeOf_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ConfigurationBinder/Version1/Get_TypeOf_BinderOptions.generated.txt @@ -69,9 +69,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value1) && TryParseInt(value1, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp2; } } else if (defaultValueIfNotFound) @@ -151,11 +151,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/BindConfiguration.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/BindConfiguration.generated.txt index 27f855aee5dc6c..fb39e67ea23995 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/BindConfiguration.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/BindConfiguration.generated.txt @@ -35,10 +35,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")] file static class BindingExtensions { - #region OptionsBuilder extensions. + #region global::Microsoft.Extensions.Options.OptionsBuilder extensions. /// Registers the dependency injection container to bind against the obtained from the DI service provider. [InterceptsLocation(@"src-0.cs", 12, 24)] - public static OptionsBuilder BindConfiguration(this OptionsBuilder optionsBuilder, string configSectionPath, Action? configureBinder = null) where TOptions : class + public static global::Microsoft.Extensions.Options.OptionsBuilder BindConfiguration(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, string configSectionPath, Action? configureBinder = null) where TOptions : class { ArgumentNullException.ThrowIfNull(optionsBuilder); @@ -59,10 +59,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return optionsBuilder; } - #endregion OptionsBuilder extensions. + #endregion global::Microsoft.Extensions.Options.OptionsBuilder extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -106,9 +106,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -119,11 +119,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -131,13 +131,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -159,17 +159,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -216,11 +216,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/BindConfigurationWithConfigureActions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/BindConfigurationWithConfigureActions.generated.txt index 27f855aee5dc6c..fb39e67ea23995 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/BindConfigurationWithConfigureActions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/BindConfigurationWithConfigureActions.generated.txt @@ -35,10 +35,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")] file static class BindingExtensions { - #region OptionsBuilder extensions. + #region global::Microsoft.Extensions.Options.OptionsBuilder extensions. /// Registers the dependency injection container to bind against the obtained from the DI service provider. [InterceptsLocation(@"src-0.cs", 12, 24)] - public static OptionsBuilder BindConfiguration(this OptionsBuilder optionsBuilder, string configSectionPath, Action? configureBinder = null) where TOptions : class + public static global::Microsoft.Extensions.Options.OptionsBuilder BindConfiguration(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, string configSectionPath, Action? configureBinder = null) where TOptions : class { ArgumentNullException.ThrowIfNull(optionsBuilder); @@ -59,10 +59,10 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return optionsBuilder; } - #endregion OptionsBuilder extensions. + #endregion global::Microsoft.Extensions.Options.OptionsBuilder extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -106,9 +106,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -119,11 +119,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -131,13 +131,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -159,17 +159,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -216,11 +216,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/Bind_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/Bind_T.generated.txt index 019945338cb02d..494929f8356b93 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/Bind_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/Bind_T.generated.txt @@ -35,23 +35,23 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")] file static class BindingExtensions { - #region OptionsBuilder extensions. + #region global::Microsoft.Extensions.Options.OptionsBuilder extensions. /// Registers a configuration instance which will bind against. [InterceptsLocation(@"src-0.cs", 15, 24)] - public static OptionsBuilder Bind(this OptionsBuilder optionsBuilder, IConfiguration config) where TOptions : class + public static global::Microsoft.Extensions.Options.OptionsBuilder Bind(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, IConfiguration config) where TOptions : class { return Bind(optionsBuilder, config, configureBinder: null); } /// Registers a configuration instance which will bind against. - public static OptionsBuilder Bind(this OptionsBuilder optionsBuilder, IConfiguration config, Action? configureBinder) where TOptions : class + public static global::Microsoft.Extensions.Options.OptionsBuilder Bind(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, IConfiguration config, Action? configureBinder) where TOptions : class { ArgumentNullException.ThrowIfNull(optionsBuilder); Configure(optionsBuilder.Services, optionsBuilder.Name, config, configureBinder); return optionsBuilder; } - #endregion OptionsBuilder extensions. + #endregion global::Microsoft.Extensions.Options.OptionsBuilder extensions. #region IServiceCollection extensions. /// Registers a configuration instance which TOptions will bind against. @@ -68,7 +68,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -100,9 +100,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -112,9 +112,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -125,11 +125,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -137,13 +137,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -165,17 +165,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -222,11 +222,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/Bind_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/Bind_T_BinderOptions.generated.txt index e816b00c30c64f..50c1f9dec556c3 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/Bind_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version0/Bind_T_BinderOptions.generated.txt @@ -35,17 +35,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")] file static class BindingExtensions { - #region OptionsBuilder extensions. + #region global::Microsoft.Extensions.Options.OptionsBuilder extensions. /// Registers a configuration instance which will bind against. [InterceptsLocation(@"src-0.cs", 15, 24)] - public static OptionsBuilder Bind(this OptionsBuilder optionsBuilder, IConfiguration config, Action? configureBinder) where TOptions : class + public static global::Microsoft.Extensions.Options.OptionsBuilder Bind(this global::Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, IConfiguration config, Action? configureBinder) where TOptions : class { ArgumentNullException.ThrowIfNull(optionsBuilder); Configure(optionsBuilder.Services, optionsBuilder.Name, config, configureBinder); return optionsBuilder; } - #endregion OptionsBuilder extensions. + #endregion global::Microsoft.Extensions.Options.OptionsBuilder extensions. #region IServiceCollection extensions. /// Registers a configuration instance which TOptions will bind against. @@ -62,7 +62,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -106,9 +106,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -119,11 +119,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -131,13 +131,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -159,17 +159,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -216,11 +216,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/BindConfiguration.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/BindConfiguration.generated.txt index d66b850ec73a64..3ef62e8b629843 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/BindConfiguration.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/BindConfiguration.generated.txt @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -106,9 +106,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -119,11 +119,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -131,13 +131,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -216,11 +216,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/BindConfigurationWithConfigureActions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/BindConfigurationWithConfigureActions.generated.txt index 32ee775fe8bb0b..b4260b3504b6fd 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/BindConfigurationWithConfigureActions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/BindConfigurationWithConfigureActions.generated.txt @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -106,9 +106,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -119,11 +119,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -131,13 +131,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -216,11 +216,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/Bind_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/Bind_T.generated.txt index c152aae35ed352..c57e838206871d 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/Bind_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/Bind_T.generated.txt @@ -100,9 +100,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -112,9 +112,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -125,11 +125,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -137,13 +137,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -222,11 +222,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/Bind_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/Bind_T_BinderOptions.generated.txt index b6d2f75982baaf..b8449faa19fa7f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/Bind_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/OptionsBuilder/Version1/Bind_T_BinderOptions.generated.txt @@ -94,9 +94,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -106,9 +106,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value2)) { - instance.MyString = value1; + instance.MyString = value2; } else if (defaultValueIfNotFound) { @@ -119,11 +119,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value3)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.MyInt = ParseInt(value2, configuration.GetSection("MyInt").Path); + instance.MyInt = temp4; } } else if (defaultValueIfNotFound) @@ -131,13 +131,13 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value3 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value3) is IConfigurationSection section4) + var value5 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp6 = instance.MyList; - temp6 ??= new global::System.Collections.Generic.List(); - BindCore(section4, ref temp6, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp6; + global::System.Collections.Generic.List? temp8 = instance.MyList; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp8; } else { @@ -216,11 +216,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T.generated.txt index e9ecaf5c678dab..6174e13ecbb779 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T.generated.txt @@ -58,8 +58,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -91,9 +91,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -103,11 +103,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -145,9 +145,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -158,11 +158,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -170,39 +170,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -224,17 +224,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -281,11 +281,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_BinderOptions.generated.txt index 0ed9bbf43db362..058de0ef8be7ed 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_BinderOptions.generated.txt @@ -58,8 +58,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -91,9 +91,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -103,11 +103,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -145,9 +145,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -158,11 +158,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -170,39 +170,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -224,17 +224,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -281,11 +281,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_name.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_name.generated.txt index a3314cd575dc12..41aff7757f2ca7 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_name.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_name.generated.txt @@ -58,8 +58,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -91,9 +91,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -103,11 +103,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -145,9 +145,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -158,11 +158,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -170,39 +170,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -224,17 +224,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -281,11 +281,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_name_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_name_BinderOptions.generated.txt index 033756d6fab93c..4441dce59cb8d2 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_name_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version0/Configure_T_name_BinderOptions.generated.txt @@ -52,8 +52,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IServiceCollection extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); + private readonly static Lazy> s_configKeys_Program__MyClass2 = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyInt" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "MyString", "MyInt", "MyList", "MyList2", "MyDictionary" }); public static void BindCoreMain(IConfiguration configuration, object instance, Type type, Action? configureOptions) { @@ -85,9 +85,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -97,11 +97,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -139,9 +139,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -152,11 +152,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -164,39 +164,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -218,17 +218,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -275,11 +275,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T.generated.txt index d9645e2b579072..18f46ca82a7672 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T.generated.txt @@ -91,9 +91,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -103,11 +103,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -145,9 +145,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -158,11 +158,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -170,39 +170,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -281,11 +281,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_BinderOptions.generated.txt index 065a4d45a779f2..ae52643be465a4 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_BinderOptions.generated.txt @@ -91,9 +91,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -103,11 +103,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -145,9 +145,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -158,11 +158,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -170,39 +170,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -281,11 +281,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_name.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_name.generated.txt index eeafcceb582d8c..736e53ba2e862c 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_name.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_name.generated.txt @@ -91,9 +91,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -103,11 +103,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -145,9 +145,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -158,11 +158,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -170,39 +170,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -281,11 +281,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_name_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_name_BinderOptions.generated.txt index 6bcaeac55f93a6..fb1d08199939c1 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_name_BinderOptions.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/ServiceCollection/Version1/Configure_T_name_BinderOptions.generated.txt @@ -85,9 +85,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance.Add(ParseInt(value, section.Path)); + instance.Add(temp1); } } } @@ -97,11 +97,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass2), s_configKeys_Program__MyClass2, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseInt(value2, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - instance.MyInt = ParseInt(value1, configuration.GetSection("MyInt").Path); + instance.MyInt = temp3; } } else if (defaultValueIfNotFound) @@ -139,9 +139,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClass), s_configKeys_Program__MyClass, configuration, binderOptions); - if (TryGetConfigurationValue(configuration, key: "MyString", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "MyString", out string? value5)) { - instance.MyString = value3; + instance.MyString = value5; } else if (defaultValueIfNotFound) { @@ -152,11 +152,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "MyInt", out string? value6)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value6) && TryParseInt(value6, configuration.GetSection("MyInt").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp7)) { - instance.MyInt = ParseInt(value4, configuration.GetSection("MyInt").Path); + instance.MyInt = temp7; } } else if (defaultValueIfNotFound) @@ -164,39 +164,39 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.MyInt = instance.MyInt; } - var value5 = configuration.GetSection("MyList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("MyList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::System.Collections.Generic.List? temp8 = instance.MyList; - temp8 ??= new global::System.Collections.Generic.List(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.MyList = temp8; + global::System.Collections.Generic.List? temp11 = instance.MyList; + temp11 ??= new global::System.Collections.Generic.List(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.MyList = temp11; } else { instance.MyList = instance.MyList; } - var value9 = configuration.GetSection("MyList2"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("MyList2"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.List? temp12 = instance.MyList2; - temp12 ??= new global::System.Collections.Generic.List(); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.MyList2 = temp12; + global::System.Collections.Generic.List? temp15 = instance.MyList2; + temp15 ??= new global::System.Collections.Generic.List(); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.MyList2 = temp15; } else { instance.MyList2 = instance.MyList2; } - var value13 = configuration.GetSection("MyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("MyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.Dictionary? temp16 = instance.MyDictionary; - temp16 ??= new global::System.Collections.Generic.Dictionary(); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.MyDictionary = temp16; + global::System.Collections.Generic.Dictionary? temp19 = instance.MyDictionary; + temp19 ??= new global::System.Collections.Generic.Dictionary(); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.MyDictionary = temp19; } else { @@ -275,11 +275,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/Collections.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/Collections.generated.txt index e1d45a2f21084d..e5986de6d27699 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/Collections.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/Collections.generated.txt @@ -41,7 +41,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClassWithCustomCollections = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "CustomDictionary", "CustomList", "ICustomDictionary", "ICustomCollection", "IReadOnlyList", "UnsupportedIReadOnlyDictionaryUnsupported", "IReadOnlyDictionary", "CollectionStructExplicit" }); + private readonly static Lazy> s_configKeys_Program__MyClassWithCustomCollections = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "CustomDictionary", "CustomList", "ICustomDictionary", "ICustomCollection", "IReadOnlyList", "UnsupportedIReadOnlyDictionaryUnsupported", "IReadOnlyDictionary", "CollectionStructExplicit" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -70,9 +70,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance[section.Key] = ParseInt(value, section.Path); + instance[section.Key] = temp1; } } } @@ -91,7 +91,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.IReadOnlyList instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - if (instance is not ICollection temp) + if (instance is not global::System.Collections.Generic.ICollection temp) { return; } @@ -100,9 +100,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - temp.Add(ParseInt(value, section.Path)); + temp.Add(temp2); } } } @@ -110,7 +110,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.IReadOnlyDictionary instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { - if (instance is not IDictionary temp) + if (instance is not global::System.Collections.Generic.IDictionary temp) { return; } @@ -119,9 +119,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - temp[section.Key] = ParseInt(value, section.Path); + temp[section.Key] = temp3; } } } @@ -144,66 +144,66 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClassWithCustomCollections), s_configKeys_Program__MyClassWithCustomCollections, configuration, binderOptions); - var value1 = configuration.GetSection("CustomDictionary"); - if (AsConfigWithChildren(value1) is IConfigurationSection section2) + var value4 = configuration.GetSection("CustomDictionary"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::Program.CustomDictionary? temp4 = instance.CustomDictionary; - temp4 ??= new global::Program.CustomDictionary(); - BindCore(section2, ref temp4, defaultValueIfNotFound: false, binderOptions); - instance.CustomDictionary = temp4; + global::Program.CustomDictionary? temp7 = instance.CustomDictionary; + temp7 ??= new global::Program.CustomDictionary(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.CustomDictionary = temp7; } else { instance.CustomDictionary = instance.CustomDictionary; } - var value5 = configuration.GetSection("CustomList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("CustomList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::Program.CustomList? temp8 = instance.CustomList; - temp8 ??= new global::Program.CustomList(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.CustomList = temp8; + global::Program.CustomList? temp11 = instance.CustomList; + temp11 ??= new global::Program.CustomList(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.CustomList = temp11; } else { instance.CustomList = instance.CustomList; } - var value9 = configuration.GetSection("IReadOnlyList"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("IReadOnlyList"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.IReadOnlyList? temp12 = instance.IReadOnlyList; - temp12 = temp12 is null ? (global::System.Collections.Generic.IReadOnlyList)new List() : (global::System.Collections.Generic.IReadOnlyList)new List(temp12); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.IReadOnlyList = temp12; + global::System.Collections.Generic.IReadOnlyList? temp15 = instance.IReadOnlyList; + temp15 = temp15 is null ? (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List() : (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List(temp15); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.IReadOnlyList = temp15; } else { instance.IReadOnlyList = instance.IReadOnlyList; } - var value13 = configuration.GetSection("IReadOnlyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("IReadOnlyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.IReadOnlyDictionary? temp16 = instance.IReadOnlyDictionary; - temp16 = temp16 is null ? (global::System.Collections.Generic.IReadOnlyDictionary)new Dictionary() : (global::System.Collections.Generic.IReadOnlyDictionary)temp16.ToDictionary(pair => pair.Key, pair => pair.Value); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.IReadOnlyDictionary = temp16; + global::System.Collections.Generic.IReadOnlyDictionary? temp19 = instance.IReadOnlyDictionary; + temp19 = temp19 is null ? (global::System.Collections.Generic.IReadOnlyDictionary)new global::System.Collections.Generic.Dictionary() : (global::System.Collections.Generic.IReadOnlyDictionary)temp19.ToDictionary(pair => pair.Key, pair => pair.Value); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.IReadOnlyDictionary = temp19; } else { instance.IReadOnlyDictionary = instance.IReadOnlyDictionary; } - var value17 = configuration.GetSection("CollectionStructExplicit"); - if (AsConfigWithChildren(value17) is IConfigurationSection section18) + var value20 = configuration.GetSection("CollectionStructExplicit"); + if (AsConfigWithChildren(value20) is IConfigurationSection section21) { - global::Program.CollectionStructExplicit temp19 = instance.CollectionStructExplicit; - var temp20 = new global::Program.CollectionStructExplicit(); - BindCore(section18, ref temp20, defaultValueIfNotFound: false, binderOptions); - instance.CollectionStructExplicit = temp20; - temp19 = temp20; + global::Program.CollectionStructExplicit temp22 = instance.CollectionStructExplicit; + var temp23 = new global::Program.CollectionStructExplicit(); + BindCore(section21, ref temp23, defaultValueIfNotFound: false, binderOptions); + instance.CollectionStructExplicit = temp23; + temp22 = temp23; } else { @@ -225,17 +225,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -282,11 +282,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/DefaultConstructorParameters.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/DefaultConstructorParameters.generated.txt index aad7e722200055..e6bc3d8fb2df33 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/DefaultConstructorParameters.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/DefaultConstructorParameters.generated.txt @@ -51,7 +51,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__ClassWhereParametersHaveDefaultValue = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "Name", "Address", "Age", "F", "D", "M", "SC", "C", "NAge", "NF", "ND", "NM", "NSC", "NC" }); + private readonly static Lazy> s_configKeys_Program__ClassWhereParametersHaveDefaultValue = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "Name", "Address", "Age", "F", "D", "M", "SC", "C", "NAge", "NF", "ND", "NM", "NSC", "NC" }); public static void BindCore(IConfiguration configuration, ref global::Program.ClassWhereParametersHaveDefaultValue instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { @@ -63,161 +63,157 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration string name = "John Doe"!; if (TryGetConfigurationValue(configuration, key: "Name", out string? value0)) { - name = value0; + if (value0 is null) + { + name = "John Doe"; + } + else + { + name = value0; + } } string address = "1 Microsoft Way"!; if (TryGetConfigurationValue(configuration, key: "Address", out string? value1)) { - address = value1; + if (value1 is null) + { + address = "1 Microsoft Way"; + } + else + { + address = value1; + } } int age = (int)(42); - if (TryGetConfigurationValue(configuration, key: "Age", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "Age", out string? value2) && value2 is not null && TryParseInt(value2, configuration.GetSection("Age").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - if (!string.IsNullOrEmpty(value2)) - { - age = ParseInt(value2, configuration.GetSection("Age").Path); - } + age = temp3; } float f = 42F; - if (TryGetConfigurationValue(configuration, key: "F", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "F", out string? value4) && value4 is not null && TryParseFloat(value4, configuration.GetSection("F").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp5)) { - if (!string.IsNullOrEmpty(value3)) - { - f = ParseFloat(value3, configuration.GetSection("F").Path); - } + f = temp5; } double d = 3.1415899999999999D; - if (TryGetConfigurationValue(configuration, key: "D", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "D", out string? value6) && value6 is not null && TryParseDouble(value6, configuration.GetSection("D").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp7)) { - if (!string.IsNullOrEmpty(value4)) - { - d = ParseDouble(value4, configuration.GetSection("D").Path); - } + d = temp7; } decimal m = 3.1415926535897932384626433M; - if (TryGetConfigurationValue(configuration, key: "M", out string? value5)) + if (TryGetConfigurationValue(configuration, key: "M", out string? value8) && value8 is not null && TryParseDecimal(value8, configuration.GetSection("M").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp9)) { - if (!string.IsNullOrEmpty(value5)) - { - m = ParseDecimal(value5, configuration.GetSection("M").Path); - } + m = temp9; } global::System.StringComparison sc = (global::System.StringComparison)(4); - if (TryGetConfigurationValue(configuration, key: "SC", out string? value6)) + if (TryGetConfigurationValue(configuration, key: "SC", out string? value10) && value10 is not null && TryParseEnum(value10, configuration.GetSection("SC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.StringComparison temp11)) { - if (!string.IsNullOrEmpty(value6)) - { - sc = ParseEnum(value6, configuration.GetSection("SC").Path); - } + sc = temp11; } char c = 'q'; - if (TryGetConfigurationValue(configuration, key: "C", out string? value7)) + if (TryGetConfigurationValue(configuration, key: "C", out string? value12) && value12 is not null && TryParseChar(value12, configuration.GetSection("C").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp13)) { - if (!string.IsNullOrEmpty(value7)) - { - c = ParseChar(value7, configuration.GetSection("C").Path); - } + c = temp13; } int? nage = (int?)(42); - if (TryGetConfigurationValue(configuration, key: "NAge", out string? value8)) + if (TryGetConfigurationValue(configuration, key: "NAge", out string? value14)) { - if (value8 is null) + if (string.IsNullOrEmpty(value14)) { - nage = null; + nage = (int?)(42); } else { - if (!string.IsNullOrEmpty(value8)) + if (TryParseInt(value14, configuration.GetSection("NAge").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp15)) { - nage = ParseInt(value8, configuration.GetSection("NAge").Path); + nage = temp15; } } } float? nf = 42F; - if (TryGetConfigurationValue(configuration, key: "NF", out string? value9)) + if (TryGetConfigurationValue(configuration, key: "NF", out string? value16)) { - if (value9 is null) + if (string.IsNullOrEmpty(value16)) { - nf = null; + nf = 42F; } else { - if (!string.IsNullOrEmpty(value9)) + if (TryParseFloat(value16, configuration.GetSection("NF").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp17)) { - nf = ParseFloat(value9, configuration.GetSection("NF").Path); + nf = temp17; } } } double? nd = 3.1415899999999999D; - if (TryGetConfigurationValue(configuration, key: "ND", out string? value10)) + if (TryGetConfigurationValue(configuration, key: "ND", out string? value18)) { - if (value10 is null) + if (string.IsNullOrEmpty(value18)) { - nd = null; + nd = 3.1415899999999999D; } else { - if (!string.IsNullOrEmpty(value10)) + if (TryParseDouble(value18, configuration.GetSection("ND").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp19)) { - nd = ParseDouble(value10, configuration.GetSection("ND").Path); + nd = temp19; } } } decimal? nm = 3.1415926535897932384626433M; - if (TryGetConfigurationValue(configuration, key: "NM", out string? value11)) + if (TryGetConfigurationValue(configuration, key: "NM", out string? value20)) { - if (value11 is null) + if (string.IsNullOrEmpty(value20)) { - nm = null; + nm = 3.1415926535897932384626433M; } else { - if (!string.IsNullOrEmpty(value11)) + if (TryParseDecimal(value20, configuration.GetSection("NM").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp21)) { - nm = ParseDecimal(value11, configuration.GetSection("NM").Path); + nm = temp21; } } } global::System.StringComparison? nsc = (global::System.StringComparison?)(4); - if (TryGetConfigurationValue(configuration, key: "NSC", out string? value12)) + if (TryGetConfigurationValue(configuration, key: "NSC", out string? value22)) { - if (value12 is null) + if (string.IsNullOrEmpty(value22)) { - nsc = null; + nsc = (global::System.StringComparison?)(4); } else { - if (!string.IsNullOrEmpty(value12)) + if (TryParseEnum(value22, configuration.GetSection("NSC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.StringComparison temp23)) { - nsc = ParseEnum(value12, configuration.GetSection("NSC").Path); + nsc = temp23; } } } char? nc = 'q'; - if (TryGetConfigurationValue(configuration, key: "NC", out string? value13)) + if (TryGetConfigurationValue(configuration, key: "NC", out string? value24)) { - if (value13 is null) + if (string.IsNullOrEmpty(value24)) { - nc = null; + nc = 'q'; } else { - if (!string.IsNullOrEmpty(value13)) + if (TryParseChar(value24, configuration.GetSection("NC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp25)) { - nc = ParseChar(value13, configuration.GetSection("NC").Path); + nc = temp25; } } } @@ -239,17 +235,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -260,11 +256,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, string? path) where T : struct + public static bool TryParseEnum(string value, string? path, bool errorOnFailedBinding, out T result) where T : struct { try { - return Enum.Parse(value, ignoreCase: true); + result = Enum.Parse(value, ignoreCase: true); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -272,11 +274,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -284,11 +292,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -296,11 +310,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -308,11 +328,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static decimal ParseDecimal(string value, string? path) + public static bool TryParseDecimal(string value, string? path, bool errorOnFailedBinding, out decimal result) { try { - return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -320,11 +346,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static char ParseChar(string value, string? path) + public static bool TryParseChar(string value, string? path, bool errorOnFailedBinding, out char result) { try { - return char.Parse(value); + result = char.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/EmptyConfigType.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/EmptyConfigType.generated.txt index df2c86e2e8816d..82d96fd0f16e3a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/EmptyConfigType.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/EmptyConfigType.generated.txt @@ -58,7 +58,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_TypeWithNoMembers_Wrapper = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "Member" }); + private readonly static Lazy> s_configKeys_TypeWithNoMembers_Wrapper = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "Member" }); public static void BindCore(IConfiguration configuration, ref global::TypeWithNoMembers_Wrapper instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { @@ -85,17 +85,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/Primitives.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/Primitives.generated.txt index 75c6699e61fa69..cbc86cf9e4cd4b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/Primitives.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/Primitives.generated.txt @@ -51,7 +51,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "Prop0", "Prop1", "Prop2", "Prop3", "Prop4", "Prop5", "Prop6", "Prop8", "Prop9", "Prop10", "Prop13", "Prop14", "Prop15", "Prop16", "Prop17", "Prop19", "Prop20", "Prop21", "Prop23", "Prop24", "Prop25", "Prop26", "Prop27", "Prop7", "Prop11", "Prop12", "Prop18", "Prop22", "Prop28", "Prop29", "Prop30" }); + private readonly static Lazy> s_configKeys_Program__MyClass = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "Prop0", "Prop1", "Prop2", "Prop3", "Prop4", "Prop5", "Prop6", "Prop8", "Prop9", "Prop10", "Prop13", "Prop14", "Prop15", "Prop16", "Prop17", "Prop19", "Prop20", "Prop21", "Prop23", "Prop24", "Prop25", "Prop26", "Prop27", "Prop7", "Prop11", "Prop12", "Prop18", "Prop22", "Prop28", "Prop29", "Prop30" }); public static void BindCore(IConfiguration configuration, ref global::Program.MyClass instance, bool defaultValueIfNotFound, BinderOptions? binderOptions) { @@ -59,9 +59,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "Prop0", out string? value0)) { - if (!string.IsNullOrEmpty(value0)) + if (!string.IsNullOrEmpty(value0) && TryParseBool(value0, configuration.GetSection("Prop0").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out bool temp1)) { - instance.Prop0 = ParseBool(value0, configuration.GetSection("Prop0").Path); + instance.Prop0 = temp1; } } else if (defaultValueIfNotFound) @@ -69,11 +69,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop0 = instance.Prop0; } - if (TryGetConfigurationValue(configuration, key: "Prop1", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "Prop1", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseByte(value2, configuration.GetSection("Prop1").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte temp3)) { - instance.Prop1 = ParseByte(value1, configuration.GetSection("Prop1").Path); + instance.Prop1 = temp3; } } else if (defaultValueIfNotFound) @@ -81,11 +81,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop1 = instance.Prop1; } - if (TryGetConfigurationValue(configuration, key: "Prop2", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "Prop2", out string? value4)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value4) && TryParseSbyte(value4, configuration.GetSection("Prop2").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out sbyte temp5)) { - instance.Prop2 = ParseSbyte(value2, configuration.GetSection("Prop2").Path); + instance.Prop2 = temp5; } } else if (defaultValueIfNotFound) @@ -93,11 +93,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop2 = instance.Prop2; } - if (TryGetConfigurationValue(configuration, key: "Prop3", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "Prop3", out string? value6)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value6) && TryParseChar(value6, configuration.GetSection("Prop3").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp7)) { - instance.Prop3 = ParseChar(value3, configuration.GetSection("Prop3").Path); + instance.Prop3 = temp7; } } else if (defaultValueIfNotFound) @@ -105,11 +105,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop3 = instance.Prop3; } - if (TryGetConfigurationValue(configuration, key: "Prop4", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "Prop4", out string? value8)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value8) && TryParseDouble(value8, configuration.GetSection("Prop4").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp9)) { - instance.Prop4 = ParseDouble(value4, configuration.GetSection("Prop4").Path); + instance.Prop4 = temp9; } } else if (defaultValueIfNotFound) @@ -117,9 +117,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop4 = instance.Prop4; } - if (TryGetConfigurationValue(configuration, key: "Prop5", out string? value5)) + if (TryGetConfigurationValue(configuration, key: "Prop5", out string? value10)) { - instance.Prop5 = value5; + instance.Prop5 = value10; } else if (defaultValueIfNotFound) { @@ -130,11 +130,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop6", out string? value6)) + if (TryGetConfigurationValue(configuration, key: "Prop6", out string? value11)) { - if (!string.IsNullOrEmpty(value6)) + if (!string.IsNullOrEmpty(value11) && TryParseInt(value11, configuration.GetSection("Prop6").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp12)) { - instance.Prop6 = ParseInt(value6, configuration.GetSection("Prop6").Path); + instance.Prop6 = temp12; } } else if (defaultValueIfNotFound) @@ -142,11 +142,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop6 = instance.Prop6; } - if (TryGetConfigurationValue(configuration, key: "Prop8", out string? value7)) + if (TryGetConfigurationValue(configuration, key: "Prop8", out string? value13)) { - if (!string.IsNullOrEmpty(value7)) + if (!string.IsNullOrEmpty(value13) && TryParseShort(value13, configuration.GetSection("Prop8").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out short temp14)) { - instance.Prop8 = ParseShort(value7, configuration.GetSection("Prop8").Path); + instance.Prop8 = temp14; } } else if (defaultValueIfNotFound) @@ -154,11 +154,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop8 = instance.Prop8; } - if (TryGetConfigurationValue(configuration, key: "Prop9", out string? value8)) + if (TryGetConfigurationValue(configuration, key: "Prop9", out string? value15)) { - if (!string.IsNullOrEmpty(value8)) + if (!string.IsNullOrEmpty(value15) && TryParseLong(value15, configuration.GetSection("Prop9").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out long temp16)) { - instance.Prop9 = ParseLong(value8, configuration.GetSection("Prop9").Path); + instance.Prop9 = temp16; } } else if (defaultValueIfNotFound) @@ -166,11 +166,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop9 = instance.Prop9; } - if (TryGetConfigurationValue(configuration, key: "Prop10", out string? value9)) + if (TryGetConfigurationValue(configuration, key: "Prop10", out string? value17)) { - if (!string.IsNullOrEmpty(value9)) + if (!string.IsNullOrEmpty(value17) && TryParseFloat(value17, configuration.GetSection("Prop10").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp18)) { - instance.Prop10 = ParseFloat(value9, configuration.GetSection("Prop10").Path); + instance.Prop10 = temp18; } } else if (defaultValueIfNotFound) @@ -178,11 +178,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop10 = instance.Prop10; } - if (TryGetConfigurationValue(configuration, key: "Prop13", out string? value10)) + if (TryGetConfigurationValue(configuration, key: "Prop13", out string? value19)) { - if (!string.IsNullOrEmpty(value10)) + if (!string.IsNullOrEmpty(value19) && TryParseUshort(value19, configuration.GetSection("Prop13").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out ushort temp20)) { - instance.Prop13 = ParseUshort(value10, configuration.GetSection("Prop13").Path); + instance.Prop13 = temp20; } } else if (defaultValueIfNotFound) @@ -190,11 +190,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop13 = instance.Prop13; } - if (TryGetConfigurationValue(configuration, key: "Prop14", out string? value11)) + if (TryGetConfigurationValue(configuration, key: "Prop14", out string? value21)) { - if (!string.IsNullOrEmpty(value11)) + if (!string.IsNullOrEmpty(value21) && TryParseUint(value21, configuration.GetSection("Prop14").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out uint temp22)) { - instance.Prop14 = ParseUint(value11, configuration.GetSection("Prop14").Path); + instance.Prop14 = temp22; } } else if (defaultValueIfNotFound) @@ -202,11 +202,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop14 = instance.Prop14; } - if (TryGetConfigurationValue(configuration, key: "Prop15", out string? value12)) + if (TryGetConfigurationValue(configuration, key: "Prop15", out string? value23)) { - if (!string.IsNullOrEmpty(value12)) + if (!string.IsNullOrEmpty(value23) && TryParseUlong(value23, configuration.GetSection("Prop15").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out ulong temp24)) { - instance.Prop15 = ParseUlong(value12, configuration.GetSection("Prop15").Path); + instance.Prop15 = temp24; } } else if (defaultValueIfNotFound) @@ -214,9 +214,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop15 = instance.Prop15; } - if (TryGetConfigurationValue(configuration, key: "Prop16", out string? value13)) + if (TryGetConfigurationValue(configuration, key: "Prop16", out string? value25)) { - instance.Prop16 = value13; + instance.Prop16 = value25; } else if (defaultValueIfNotFound) { @@ -227,17 +227,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop17", out string? value14)) + if (TryGetConfigurationValue(configuration, key: "Prop17", out string? value26)) { - if (value14 is null) + if (value26 is null) { instance.Prop17 = null; } else { - if (!string.IsNullOrEmpty(value14)) + if (!string.IsNullOrEmpty(value26) && TryParseSystemGlobalizationCultureInfo(value26, configuration.GetSection("Prop17").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Globalization.CultureInfo temp27)) { - instance.Prop17 = ParseSystemGlobalizationCultureInfo(value14, configuration.GetSection("Prop17").Path); + instance.Prop17 = temp27; } } } @@ -250,11 +250,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop19", out string? value15)) + if (TryGetConfigurationValue(configuration, key: "Prop19", out string? value28)) { - if (!string.IsNullOrEmpty(value15)) + if (!string.IsNullOrEmpty(value28) && TryParseSystemDateTime(value28, configuration.GetSection("Prop19").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTime temp29)) { - instance.Prop19 = ParseSystemDateTime(value15, configuration.GetSection("Prop19").Path); + instance.Prop19 = temp29; } } else if (defaultValueIfNotFound) @@ -262,11 +262,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop19 = instance.Prop19; } - if (TryGetConfigurationValue(configuration, key: "Prop20", out string? value16)) + if (TryGetConfigurationValue(configuration, key: "Prop20", out string? value30)) { - if (!string.IsNullOrEmpty(value16)) + if (!string.IsNullOrEmpty(value30) && TryParseSystemDateTimeOffset(value30, configuration.GetSection("Prop20").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTimeOffset temp31)) { - instance.Prop20 = ParseSystemDateTimeOffset(value16, configuration.GetSection("Prop20").Path); + instance.Prop20 = temp31; } } else if (defaultValueIfNotFound) @@ -274,11 +274,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop20 = instance.Prop20; } - if (TryGetConfigurationValue(configuration, key: "Prop21", out string? value17)) + if (TryGetConfigurationValue(configuration, key: "Prop21", out string? value32)) { - if (!string.IsNullOrEmpty(value17)) + if (!string.IsNullOrEmpty(value32) && TryParseDecimal(value32, configuration.GetSection("Prop21").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp33)) { - instance.Prop21 = ParseDecimal(value17, configuration.GetSection("Prop21").Path); + instance.Prop21 = temp33; } } else if (defaultValueIfNotFound) @@ -286,11 +286,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop21 = instance.Prop21; } - if (TryGetConfigurationValue(configuration, key: "Prop23", out string? value18)) + if (TryGetConfigurationValue(configuration, key: "Prop23", out string? value34)) { - if (!string.IsNullOrEmpty(value18)) + if (!string.IsNullOrEmpty(value34) && TryParseSystemTimeSpan(value34, configuration.GetSection("Prop23").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.TimeSpan temp35)) { - instance.Prop23 = ParseSystemTimeSpan(value18, configuration.GetSection("Prop23").Path); + instance.Prop23 = temp35; } } else if (defaultValueIfNotFound) @@ -298,11 +298,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop23 = instance.Prop23; } - if (TryGetConfigurationValue(configuration, key: "Prop24", out string? value19)) + if (TryGetConfigurationValue(configuration, key: "Prop24", out string? value36)) { - if (!string.IsNullOrEmpty(value19)) + if (!string.IsNullOrEmpty(value36) && TryParseSystemGuid(value36, configuration.GetSection("Prop24").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Guid temp37)) { - instance.Prop24 = ParseSystemGuid(value19, configuration.GetSection("Prop24").Path); + instance.Prop24 = temp37; } } else if (defaultValueIfNotFound) @@ -310,17 +310,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop24 = instance.Prop24; } - if (TryGetConfigurationValue(configuration, key: "Prop25", out string? value20)) + if (TryGetConfigurationValue(configuration, key: "Prop25", out string? value38)) { - if (value20 is null) + if (value38 is null) { instance.Prop25 = null; } else { - if (!string.IsNullOrEmpty(value20)) + if (!string.IsNullOrEmpty(value38) && TryParseSystemUri(value38, configuration.GetSection("Prop25").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Uri temp39)) { - instance.Prop25 = ParseSystemUri(value20, configuration.GetSection("Prop25").Path); + instance.Prop25 = temp39; } } } @@ -333,17 +333,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop26", out string? value21)) + if (TryGetConfigurationValue(configuration, key: "Prop26", out string? value40)) { - if (value21 is null) + if (value40 is null) { instance.Prop26 = null; } else { - if (!string.IsNullOrEmpty(value21)) + if (!string.IsNullOrEmpty(value40) && TryParseSystemVersion(value40, configuration.GetSection("Prop26").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Version temp41)) { - instance.Prop26 = ParseSystemVersion(value21, configuration.GetSection("Prop26").Path); + instance.Prop26 = temp41; } } } @@ -356,11 +356,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop27", out string? value22)) + if (TryGetConfigurationValue(configuration, key: "Prop27", out string? value42)) { - if (!string.IsNullOrEmpty(value22)) + if (!string.IsNullOrEmpty(value42) && TryParseEnum(value42, configuration.GetSection("Prop27").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DayOfWeek temp43)) { - instance.Prop27 = ParseEnum(value22, configuration.GetSection("Prop27").Path); + instance.Prop27 = temp43; } } else if (defaultValueIfNotFound) @@ -368,11 +368,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop27 = instance.Prop27; } - if (TryGetConfigurationValue(configuration, key: "Prop7", out string? value23)) + if (TryGetConfigurationValue(configuration, key: "Prop7", out string? value44)) { - if (!string.IsNullOrEmpty(value23)) + if (!string.IsNullOrEmpty(value44) && TryParseSystemInt128(value44, configuration.GetSection("Prop7").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Int128 temp45)) { - instance.Prop7 = ParseSystemInt128(value23, configuration.GetSection("Prop7").Path); + instance.Prop7 = temp45; } } else if (defaultValueIfNotFound) @@ -380,11 +380,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop7 = instance.Prop7; } - if (TryGetConfigurationValue(configuration, key: "Prop11", out string? value24)) + if (TryGetConfigurationValue(configuration, key: "Prop11", out string? value46)) { - if (!string.IsNullOrEmpty(value24)) + if (!string.IsNullOrEmpty(value46) && TryParseSystemHalf(value46, configuration.GetSection("Prop11").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Half temp47)) { - instance.Prop11 = ParseSystemHalf(value24, configuration.GetSection("Prop11").Path); + instance.Prop11 = temp47; } } else if (defaultValueIfNotFound) @@ -392,11 +392,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop11 = instance.Prop11; } - if (TryGetConfigurationValue(configuration, key: "Prop12", out string? value25)) + if (TryGetConfigurationValue(configuration, key: "Prop12", out string? value48)) { - if (!string.IsNullOrEmpty(value25)) + if (!string.IsNullOrEmpty(value48) && TryParseSystemUInt128(value48, configuration.GetSection("Prop12").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.UInt128 temp49)) { - instance.Prop12 = ParseSystemUInt128(value25, configuration.GetSection("Prop12").Path); + instance.Prop12 = temp49; } } else if (defaultValueIfNotFound) @@ -404,11 +404,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop12 = instance.Prop12; } - if (TryGetConfigurationValue(configuration, key: "Prop18", out string? value26)) + if (TryGetConfigurationValue(configuration, key: "Prop18", out string? value50)) { - if (!string.IsNullOrEmpty(value26)) + if (!string.IsNullOrEmpty(value50) && TryParseSystemDateOnly(value50, configuration.GetSection("Prop18").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateOnly temp51)) { - instance.Prop18 = ParseSystemDateOnly(value26, configuration.GetSection("Prop18").Path); + instance.Prop18 = temp51; } } else if (defaultValueIfNotFound) @@ -416,11 +416,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop18 = instance.Prop18; } - if (TryGetConfigurationValue(configuration, key: "Prop22", out string? value27)) + if (TryGetConfigurationValue(configuration, key: "Prop22", out string? value52)) { - if (!string.IsNullOrEmpty(value27)) + if (!string.IsNullOrEmpty(value52) && TryParseSystemTimeOnly(value52, configuration.GetSection("Prop22").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.TimeOnly temp53)) { - instance.Prop22 = ParseSystemTimeOnly(value27, configuration.GetSection("Prop22").Path); + instance.Prop22 = temp53; } } else if (defaultValueIfNotFound) @@ -428,21 +428,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop22 = instance.Prop22; } - if (TryGetConfigurationValue(configuration, key: "Prop28", out string? value28)) + if (TryGetConfigurationValue(configuration, key: "Prop28", out string? value54)) { - if (value28 is null) + if (value54 is null) { instance.Prop28 = null; } else { - if (value28 == string.Empty) + if (value54 == string.Empty && TryParseByteArray(value54, configuration.GetSection("Prop28").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte[] temp55)) { - instance.Prop28 = ParseByteArray(value28, configuration.GetSection("Prop28").Path); + instance.Prop28 = temp55; } - else if (!string.IsNullOrEmpty(value28)) + else if (!string.IsNullOrEmpty(value54) && TryParseByteArray(value54, configuration.GetSection("Prop28").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte[] temp56)) { - instance.Prop28 = ParseByteArray(value28, configuration.GetSection("Prop28").Path); + instance.Prop28 = temp56; } } } @@ -455,11 +455,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop29", out string? value29)) + if (TryGetConfigurationValue(configuration, key: "Prop29", out string? value57)) { - if (!string.IsNullOrEmpty(value29)) + if (!string.IsNullOrEmpty(value57) && TryParseInt(value57, configuration.GetSection("Prop29").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp58)) { - instance.Prop29 = ParseInt(value29, configuration.GetSection("Prop29").Path); + instance.Prop29 = temp58; } } else if (defaultValueIfNotFound) @@ -467,11 +467,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop29 = instance.Prop29; } - if (TryGetConfigurationValue(configuration, key: "Prop30", out string? value30)) + if (TryGetConfigurationValue(configuration, key: "Prop30", out string? value59)) { - if (!string.IsNullOrEmpty(value30)) + if (!string.IsNullOrEmpty(value59) && TryParseSystemDateTime(value59, configuration.GetSection("Prop30").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTime temp60)) { - instance.Prop30 = ParseSystemDateTime(value30, configuration.GetSection("Prop30").Path); + instance.Prop30 = temp60; } } else if (defaultValueIfNotFound) @@ -494,17 +494,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -515,11 +515,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, string? path) where T : struct + public static bool TryParseEnum(string value, string? path, bool errorOnFailedBinding, out T result) where T : struct { try { - return Enum.Parse(value, ignoreCase: true); + result = Enum.Parse(value, ignoreCase: true); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -527,11 +533,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -539,11 +551,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static byte ParseByte(string value, string? path) + public static bool TryParseByte(string value, string? path, bool errorOnFailedBinding, out byte result) { try { - return byte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = byte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -551,11 +569,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static sbyte ParseSbyte(string value, string? path) + public static bool TryParseSbyte(string value, string? path, bool errorOnFailedBinding, out sbyte result) { try { - return sbyte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = sbyte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -563,11 +587,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static char ParseChar(string value, string? path) + public static bool TryParseChar(string value, string? path, bool errorOnFailedBinding, out char result) { try { - return char.Parse(value); + result = char.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -575,11 +605,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -587,11 +623,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -599,11 +641,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static short ParseShort(string value, string? path) + public static bool TryParseShort(string value, string? path, bool errorOnFailedBinding, out short result) { try { - return short.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = short.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -611,11 +659,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static long ParseLong(string value, string? path) + public static bool TryParseLong(string value, string? path, bool errorOnFailedBinding, out long result) { try { - return long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -623,11 +677,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -635,11 +695,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static ushort ParseUshort(string value, string? path) + public static bool TryParseUshort(string value, string? path, bool errorOnFailedBinding, out ushort result) { try { - return ushort.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = ushort.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -647,11 +713,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static uint ParseUint(string value, string? path) + public static bool TryParseUint(string value, string? path, bool errorOnFailedBinding, out uint result) { try { - return uint.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = uint.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -659,11 +731,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static ulong ParseUlong(string value, string? path) + public static bool TryParseUlong(string value, string? path, bool errorOnFailedBinding, out ulong result) { try { - return ulong.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = ulong.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -671,11 +749,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -683,11 +767,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.DateTime ParseSystemDateTime(string value, string? path) + public static bool TryParseSystemDateTime(string value, string? path, bool errorOnFailedBinding, out global::System.DateTime result) { try { - return global::System.DateTime.Parse(value, CultureInfo.InvariantCulture); + result = global::System.DateTime.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -695,11 +785,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.DateTimeOffset ParseSystemDateTimeOffset(string value, string? path) + public static bool TryParseSystemDateTimeOffset(string value, string? path, bool errorOnFailedBinding, out global::System.DateTimeOffset result) { try { - return global::System.DateTimeOffset.Parse(value, CultureInfo.InvariantCulture); + result = global::System.DateTimeOffset.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -707,11 +803,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static decimal ParseDecimal(string value, string? path) + public static bool TryParseDecimal(string value, string? path, bool errorOnFailedBinding, out decimal result) { try { - return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -719,11 +821,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.TimeSpan ParseSystemTimeSpan(string value, string? path) + public static bool TryParseSystemTimeSpan(string value, string? path, bool errorOnFailedBinding, out global::System.TimeSpan result) { try { - return global::System.TimeSpan.Parse(value, CultureInfo.InvariantCulture); + result = global::System.TimeSpan.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -731,11 +839,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Guid ParseSystemGuid(string value, string? path) + public static bool TryParseSystemGuid(string value, string? path, bool errorOnFailedBinding, out global::System.Guid result) { try { - return global::System.Guid.Parse(value); + result = global::System.Guid.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -743,11 +857,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Uri ParseSystemUri(string value, string? path) + public static bool TryParseSystemUri(string value, string? path, bool errorOnFailedBinding, out global::System.Uri result) { try { - return new Uri(value, UriKind.RelativeOrAbsolute); + result = new Uri(value, UriKind.RelativeOrAbsolute); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -755,11 +875,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Version ParseSystemVersion(string value, string? path) + public static bool TryParseSystemVersion(string value, string? path, bool errorOnFailedBinding, out global::System.Version result) { try { - return global::System.Version.Parse(value); + result = global::System.Version.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -767,11 +893,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Int128 ParseSystemInt128(string value, string? path) + public static bool TryParseSystemInt128(string value, string? path, bool errorOnFailedBinding, out global::System.Int128 result) { try { - return global::System.Int128.Parse(value, CultureInfo.InvariantCulture); + result = global::System.Int128.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -779,11 +911,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Half ParseSystemHalf(string value, string? path) + public static bool TryParseSystemHalf(string value, string? path, bool errorOnFailedBinding, out global::System.Half result) { try { - return global::System.Half.Parse(value, CultureInfo.InvariantCulture); + result = global::System.Half.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -791,11 +929,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.UInt128 ParseSystemUInt128(string value, string? path) + public static bool TryParseSystemUInt128(string value, string? path, bool errorOnFailedBinding, out global::System.UInt128 result) { try { - return global::System.UInt128.Parse(value, CultureInfo.InvariantCulture); + result = global::System.UInt128.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -803,11 +947,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.DateOnly ParseSystemDateOnly(string value, string? path) + public static bool TryParseSystemDateOnly(string value, string? path, bool errorOnFailedBinding, out global::System.DateOnly result) { try { - return global::System.DateOnly.Parse(value, CultureInfo.InvariantCulture); + result = global::System.DateOnly.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -815,11 +965,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.TimeOnly ParseSystemTimeOnly(string value, string? path) + public static bool TryParseSystemTimeOnly(string value, string? path, bool errorOnFailedBinding, out global::System.TimeOnly result) { try { - return global::System.TimeOnly.Parse(value, CultureInfo.InvariantCulture); + result = global::System.TimeOnly.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -827,11 +983,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static byte[] ParseByteArray(string value, string? path) + public static bool TryParseByteArray(string value, string? path, bool errorOnFailedBinding, out byte[] result) { try { - return Convert.FromBase64String(value); + result = Convert.FromBase64String(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/UnsupportedTypes.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/UnsupportedTypes.generated.txt index b257069a90df09..78356b8fc4adda 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/UnsupportedTypes.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version0/UnsupportedTypes.generated.txt @@ -57,8 +57,8 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration #endregion IConfiguration extensions. #region Core binding extensions. - private readonly static Lazy> s_configKeys_Record___System__Action___ = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "x" }); - private readonly static Lazy> s_configKeys_Options = new(() => new HashSet(StringComparer.OrdinalIgnoreCase) { "Name", "Age", "List", "Array", "Record" }); + private readonly static Lazy> s_configKeys_Record___System__Action___ = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "x" }); + private readonly static Lazy> s_configKeys_Options = new(() => new global::System.Collections.Generic.HashSet(StringComparer.OrdinalIgnoreCase) { "Name", "Age", "List", "Array", "Record" }); public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) { @@ -139,9 +139,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "Age", out string? value3)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("Age").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.Age = ParseInt(value3, configuration.GetSection("Age").Path); + instance.Age = temp4; } } else if (defaultValueIfNotFound) @@ -149,43 +149,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Age = instance.Age; } - var value4 = configuration.GetSection("List"); - if (AsConfigWithChildren(value4) is IConfigurationSection section5) + var value5 = configuration.GetSection("List"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp7 = instance.List; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.List = temp7; + global::System.Collections.Generic.List? temp8 = instance.List; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.List = temp8; } else { instance.List = instance.List; } - var value8 = configuration.GetSection("Array"); - if (AsConfigWithChildren(value8) is IConfigurationSection section9) + var value9 = configuration.GetSection("Array"); + if (AsConfigWithChildren(value9) is IConfigurationSection section10) { - string[]? temp11 = instance.Array; - temp11 ??= new string[0]; - BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); - instance.Array = temp11; + string[]? temp12 = instance.Array; + temp12 ??= new string[0]; + BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); + instance.Array = temp12; } else { instance.Array = instance.Array; } - if (instance.Array is null && TryGetConfigurationValue(value8, key: null, out string? value12) && value12 == string.Empty) + if (instance.Array is null && TryGetConfigurationValue(value9, key: null, out string? value13) && value13 == string.Empty) { instance.Array = global::System.Array.Empty(); } - var value13 = configuration.GetSection("Record"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value14 = configuration.GetSection("Record"); + if (AsConfigWithChildren(value14) is IConfigurationSection section15) { - global::Record? temp16 = instance.Record; - temp16 ??= InitializeRecord___System__Action___(section14, binderOptions); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.Record = temp16; + global::Record? temp17 = instance.Record; + temp17 ??= InitializeRecord___System__Action___(section15, binderOptions); + BindCore(section15, ref temp17, defaultValueIfNotFound: false, binderOptions); + instance.Record = temp17; } else { @@ -196,12 +196,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static global::Record InitializeRecord___System__Action___(IConfiguration configuration, BinderOptions? binderOptions) { int x = (int)(10); - if (TryGetConfigurationValue(configuration, key: "x", out string? value17)) + if (TryGetConfigurationValue(configuration, key: "x", out string? value18) && value18 is not null && TryParseInt(value18, configuration.GetSection("x").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp19)) { - if (!string.IsNullOrEmpty(value17)) - { - x = ParseInt(value17, configuration.GetSection("x").Path); - } + x = temp19; } return new global::Record(x) @@ -224,17 +221,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration /// If required by the binder options, validates that there are no unknown keys in the input configuration object. - public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) + public static void ValidateConfigurationKeys(Type type, Lazy> keys, IConfiguration configuration, BinderOptions? binderOptions) { if (binderOptions?.ErrorOnUnknownConfiguration is true) { - List? temp = null; + global::System.Collections.Generic.List? temp = null; foreach (IConfigurationSection section in configuration.GetChildren()) { if (!keys.Value.Contains(section.Key)) { - (temp ??= new List()).Add($"'{section.Key}'"); + (temp ??= new global::System.Collections.Generic.List()).Add($"'{section.Key}'"); } } @@ -281,11 +278,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/Collections.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/Collections.generated.txt index 5de3a0ef86dd9d..90fb578dbb8336 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/Collections.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/Collections.generated.txt @@ -70,9 +70,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp1)) { - instance[section.Key] = ParseInt(value, section.Path); + instance[section.Key] = temp1; } } } @@ -100,9 +100,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp2)) { - temp.Add(ParseInt(value, section.Path)); + temp.Add(temp2); } } } @@ -119,9 +119,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { if (TryGetConfigurationValue(section, key: null, out string? value)) { - if (!string.IsNullOrEmpty(value)) + if (!string.IsNullOrEmpty(value) && TryParseInt(value, section.Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - temp[section.Key] = ParseInt(value, section.Path); + temp[section.Key] = temp3; } } } @@ -144,66 +144,66 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { ValidateConfigurationKeys(typeof(global::Program.MyClassWithCustomCollections), s_configKeys_Program__MyClassWithCustomCollections, configuration, binderOptions); - var value1 = configuration.GetSection("CustomDictionary"); - if (AsConfigWithChildren(value1) is IConfigurationSection section2) + var value4 = configuration.GetSection("CustomDictionary"); + if (AsConfigWithChildren(value4) is IConfigurationSection section5) { - global::Program.CustomDictionary? temp4 = instance.CustomDictionary; - temp4 ??= new global::Program.CustomDictionary(); - BindCore(section2, ref temp4, defaultValueIfNotFound: false, binderOptions); - instance.CustomDictionary = temp4; + global::Program.CustomDictionary? temp7 = instance.CustomDictionary; + temp7 ??= new global::Program.CustomDictionary(); + BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); + instance.CustomDictionary = temp7; } else { instance.CustomDictionary = instance.CustomDictionary; } - var value5 = configuration.GetSection("CustomList"); - if (AsConfigWithChildren(value5) is IConfigurationSection section6) + var value8 = configuration.GetSection("CustomList"); + if (AsConfigWithChildren(value8) is IConfigurationSection section9) { - global::Program.CustomList? temp8 = instance.CustomList; - temp8 ??= new global::Program.CustomList(); - BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); - instance.CustomList = temp8; + global::Program.CustomList? temp11 = instance.CustomList; + temp11 ??= new global::Program.CustomList(); + BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); + instance.CustomList = temp11; } else { instance.CustomList = instance.CustomList; } - var value9 = configuration.GetSection("IReadOnlyList"); - if (AsConfigWithChildren(value9) is IConfigurationSection section10) + var value12 = configuration.GetSection("IReadOnlyList"); + if (AsConfigWithChildren(value12) is IConfigurationSection section13) { - global::System.Collections.Generic.IReadOnlyList? temp12 = instance.IReadOnlyList; - temp12 = temp12 is null ? (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List() : (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List(temp12); - BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); - instance.IReadOnlyList = temp12; + global::System.Collections.Generic.IReadOnlyList? temp15 = instance.IReadOnlyList; + temp15 = temp15 is null ? (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List() : (global::System.Collections.Generic.IReadOnlyList)new global::System.Collections.Generic.List(temp15); + BindCore(section13, ref temp15, defaultValueIfNotFound: false, binderOptions); + instance.IReadOnlyList = temp15; } else { instance.IReadOnlyList = instance.IReadOnlyList; } - var value13 = configuration.GetSection("IReadOnlyDictionary"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value16 = configuration.GetSection("IReadOnlyDictionary"); + if (AsConfigWithChildren(value16) is IConfigurationSection section17) { - global::System.Collections.Generic.IReadOnlyDictionary? temp16 = instance.IReadOnlyDictionary; - temp16 = temp16 is null ? (global::System.Collections.Generic.IReadOnlyDictionary)new global::System.Collections.Generic.Dictionary() : (global::System.Collections.Generic.IReadOnlyDictionary)temp16.ToDictionary(pair => pair.Key, pair => pair.Value); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.IReadOnlyDictionary = temp16; + global::System.Collections.Generic.IReadOnlyDictionary? temp19 = instance.IReadOnlyDictionary; + temp19 = temp19 is null ? (global::System.Collections.Generic.IReadOnlyDictionary)new global::System.Collections.Generic.Dictionary() : (global::System.Collections.Generic.IReadOnlyDictionary)temp19.ToDictionary(pair => pair.Key, pair => pair.Value); + BindCore(section17, ref temp19, defaultValueIfNotFound: false, binderOptions); + instance.IReadOnlyDictionary = temp19; } else { instance.IReadOnlyDictionary = instance.IReadOnlyDictionary; } - var value17 = configuration.GetSection("CollectionStructExplicit"); - if (AsConfigWithChildren(value17) is IConfigurationSection section18) + var value20 = configuration.GetSection("CollectionStructExplicit"); + if (AsConfigWithChildren(value20) is IConfigurationSection section21) { - global::Program.CollectionStructExplicit temp19 = instance.CollectionStructExplicit; - var temp20 = new global::Program.CollectionStructExplicit(); - BindCore(section18, ref temp20, defaultValueIfNotFound: false, binderOptions); - instance.CollectionStructExplicit = temp20; - temp19 = temp20; + global::Program.CollectionStructExplicit temp22 = instance.CollectionStructExplicit; + var temp23 = new global::Program.CollectionStructExplicit(); + BindCore(section21, ref temp23, defaultValueIfNotFound: false, binderOptions); + instance.CollectionStructExplicit = temp23; + temp22 = temp23; } else { @@ -282,11 +282,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/DefaultConstructorParameters.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/DefaultConstructorParameters.generated.txt index 0584ef27a06710..43bee2c67c261e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/DefaultConstructorParameters.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/DefaultConstructorParameters.generated.txt @@ -87,116 +87,134 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } int age = (int)(42); - if (TryGetConfigurationValue(configuration, key: "Age", out string? value2) && value2 is not null) + if (TryGetConfigurationValue(configuration, key: "Age", out string? value2) && value2 is not null && TryParseInt(value2, configuration.GetSection("Age").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp3)) { - age = ParseInt(value2, configuration.GetSection("Age").Path); + age = temp3; } float f = 42F; - if (TryGetConfigurationValue(configuration, key: "F", out string? value3) && value3 is not null) + if (TryGetConfigurationValue(configuration, key: "F", out string? value4) && value4 is not null && TryParseFloat(value4, configuration.GetSection("F").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp5)) { - f = ParseFloat(value3, configuration.GetSection("F").Path); + f = temp5; } double d = 3.1415899999999999D; - if (TryGetConfigurationValue(configuration, key: "D", out string? value4) && value4 is not null) + if (TryGetConfigurationValue(configuration, key: "D", out string? value6) && value6 is not null && TryParseDouble(value6, configuration.GetSection("D").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp7)) { - d = ParseDouble(value4, configuration.GetSection("D").Path); + d = temp7; } decimal m = 3.1415926535897932384626433M; - if (TryGetConfigurationValue(configuration, key: "M", out string? value5) && value5 is not null) + if (TryGetConfigurationValue(configuration, key: "M", out string? value8) && value8 is not null && TryParseDecimal(value8, configuration.GetSection("M").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp9)) { - m = ParseDecimal(value5, configuration.GetSection("M").Path); + m = temp9; } global::System.StringComparison sc = (global::System.StringComparison)(4); - if (TryGetConfigurationValue(configuration, key: "SC", out string? value6) && value6 is not null) + if (TryGetConfigurationValue(configuration, key: "SC", out string? value10) && value10 is not null && TryParseEnum(value10, configuration.GetSection("SC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.StringComparison temp11)) { - sc = ParseEnum(value6, configuration.GetSection("SC").Path); + sc = temp11; } char c = 'q'; - if (TryGetConfigurationValue(configuration, key: "C", out string? value7) && value7 is not null) + if (TryGetConfigurationValue(configuration, key: "C", out string? value12) && value12 is not null && TryParseChar(value12, configuration.GetSection("C").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp13)) { - c = ParseChar(value7, configuration.GetSection("C").Path); + c = temp13; } int? nage = (int?)(42); - if (TryGetConfigurationValue(configuration, key: "NAge", out string? value8)) + if (TryGetConfigurationValue(configuration, key: "NAge", out string? value14)) { - if (string.IsNullOrEmpty(value8)) + if (string.IsNullOrEmpty(value14)) { nage = (int?)(42); } else { - nage = ParseInt(value8, configuration.GetSection("NAge").Path); + if (TryParseInt(value14, configuration.GetSection("NAge").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp15)) + { + nage = temp15; + } } } float? nf = 42F; - if (TryGetConfigurationValue(configuration, key: "NF", out string? value9)) + if (TryGetConfigurationValue(configuration, key: "NF", out string? value16)) { - if (string.IsNullOrEmpty(value9)) + if (string.IsNullOrEmpty(value16)) { nf = 42F; } else { - nf = ParseFloat(value9, configuration.GetSection("NF").Path); + if (TryParseFloat(value16, configuration.GetSection("NF").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp17)) + { + nf = temp17; + } } } double? nd = 3.1415899999999999D; - if (TryGetConfigurationValue(configuration, key: "ND", out string? value10)) + if (TryGetConfigurationValue(configuration, key: "ND", out string? value18)) { - if (string.IsNullOrEmpty(value10)) + if (string.IsNullOrEmpty(value18)) { nd = 3.1415899999999999D; } else { - nd = ParseDouble(value10, configuration.GetSection("ND").Path); + if (TryParseDouble(value18, configuration.GetSection("ND").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp19)) + { + nd = temp19; + } } } decimal? nm = 3.1415926535897932384626433M; - if (TryGetConfigurationValue(configuration, key: "NM", out string? value11)) + if (TryGetConfigurationValue(configuration, key: "NM", out string? value20)) { - if (string.IsNullOrEmpty(value11)) + if (string.IsNullOrEmpty(value20)) { nm = 3.1415926535897932384626433M; } else { - nm = ParseDecimal(value11, configuration.GetSection("NM").Path); + if (TryParseDecimal(value20, configuration.GetSection("NM").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp21)) + { + nm = temp21; + } } } global::System.StringComparison? nsc = (global::System.StringComparison?)(4); - if (TryGetConfigurationValue(configuration, key: "NSC", out string? value12)) + if (TryGetConfigurationValue(configuration, key: "NSC", out string? value22)) { - if (string.IsNullOrEmpty(value12)) + if (string.IsNullOrEmpty(value22)) { nsc = (global::System.StringComparison?)(4); } else { - nsc = ParseEnum(value12, configuration.GetSection("NSC").Path); + if (TryParseEnum(value22, configuration.GetSection("NSC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.StringComparison temp23)) + { + nsc = temp23; + } } } char? nc = 'q'; - if (TryGetConfigurationValue(configuration, key: "NC", out string? value13)) + if (TryGetConfigurationValue(configuration, key: "NC", out string? value24)) { - if (string.IsNullOrEmpty(value13)) + if (string.IsNullOrEmpty(value24)) { nc = 'q'; } else { - nc = ParseChar(value13, configuration.GetSection("NC").Path); + if (TryParseChar(value24, configuration.GetSection("NC").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp25)) + { + nc = temp25; + } } } @@ -238,11 +256,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, string? path) where T : struct + public static bool TryParseEnum(string value, string? path, bool errorOnFailedBinding, out T result) where T : struct { try { - return Enum.Parse(value, ignoreCase: true); + result = Enum.Parse(value, ignoreCase: true); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -250,11 +274,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -262,11 +292,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -274,11 +310,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -286,11 +328,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static decimal ParseDecimal(string value, string? path) + public static bool TryParseDecimal(string value, string? path, bool errorOnFailedBinding, out decimal result) { try { - return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -298,11 +346,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static char ParseChar(string value, string? path) + public static bool TryParseChar(string value, string? path, bool errorOnFailedBinding, out char result) { try { - return char.Parse(value); + result = char.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/Primitives.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/Primitives.generated.txt index 376e88d4635d13..4329d795bf9e81 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/Primitives.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/Primitives.generated.txt @@ -59,9 +59,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "Prop0", out string? value0)) { - if (!string.IsNullOrEmpty(value0)) + if (!string.IsNullOrEmpty(value0) && TryParseBool(value0, configuration.GetSection("Prop0").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out bool temp1)) { - instance.Prop0 = ParseBool(value0, configuration.GetSection("Prop0").Path); + instance.Prop0 = temp1; } } else if (defaultValueIfNotFound) @@ -69,11 +69,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop0 = instance.Prop0; } - if (TryGetConfigurationValue(configuration, key: "Prop1", out string? value1)) + if (TryGetConfigurationValue(configuration, key: "Prop1", out string? value2)) { - if (!string.IsNullOrEmpty(value1)) + if (!string.IsNullOrEmpty(value2) && TryParseByte(value2, configuration.GetSection("Prop1").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte temp3)) { - instance.Prop1 = ParseByte(value1, configuration.GetSection("Prop1").Path); + instance.Prop1 = temp3; } } else if (defaultValueIfNotFound) @@ -81,11 +81,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop1 = instance.Prop1; } - if (TryGetConfigurationValue(configuration, key: "Prop2", out string? value2)) + if (TryGetConfigurationValue(configuration, key: "Prop2", out string? value4)) { - if (!string.IsNullOrEmpty(value2)) + if (!string.IsNullOrEmpty(value4) && TryParseSbyte(value4, configuration.GetSection("Prop2").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out sbyte temp5)) { - instance.Prop2 = ParseSbyte(value2, configuration.GetSection("Prop2").Path); + instance.Prop2 = temp5; } } else if (defaultValueIfNotFound) @@ -93,11 +93,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop2 = instance.Prop2; } - if (TryGetConfigurationValue(configuration, key: "Prop3", out string? value3)) + if (TryGetConfigurationValue(configuration, key: "Prop3", out string? value6)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value6) && TryParseChar(value6, configuration.GetSection("Prop3").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out char temp7)) { - instance.Prop3 = ParseChar(value3, configuration.GetSection("Prop3").Path); + instance.Prop3 = temp7; } } else if (defaultValueIfNotFound) @@ -105,11 +105,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop3 = instance.Prop3; } - if (TryGetConfigurationValue(configuration, key: "Prop4", out string? value4)) + if (TryGetConfigurationValue(configuration, key: "Prop4", out string? value8)) { - if (!string.IsNullOrEmpty(value4)) + if (!string.IsNullOrEmpty(value8) && TryParseDouble(value8, configuration.GetSection("Prop4").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out double temp9)) { - instance.Prop4 = ParseDouble(value4, configuration.GetSection("Prop4").Path); + instance.Prop4 = temp9; } } else if (defaultValueIfNotFound) @@ -117,9 +117,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop4 = instance.Prop4; } - if (TryGetConfigurationValue(configuration, key: "Prop5", out string? value5)) + if (TryGetConfigurationValue(configuration, key: "Prop5", out string? value10)) { - instance.Prop5 = value5; + instance.Prop5 = value10; } else if (defaultValueIfNotFound) { @@ -130,11 +130,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop6", out string? value6)) + if (TryGetConfigurationValue(configuration, key: "Prop6", out string? value11)) { - if (!string.IsNullOrEmpty(value6)) + if (!string.IsNullOrEmpty(value11) && TryParseInt(value11, configuration.GetSection("Prop6").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp12)) { - instance.Prop6 = ParseInt(value6, configuration.GetSection("Prop6").Path); + instance.Prop6 = temp12; } } else if (defaultValueIfNotFound) @@ -142,11 +142,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop6 = instance.Prop6; } - if (TryGetConfigurationValue(configuration, key: "Prop8", out string? value7)) + if (TryGetConfigurationValue(configuration, key: "Prop8", out string? value13)) { - if (!string.IsNullOrEmpty(value7)) + if (!string.IsNullOrEmpty(value13) && TryParseShort(value13, configuration.GetSection("Prop8").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out short temp14)) { - instance.Prop8 = ParseShort(value7, configuration.GetSection("Prop8").Path); + instance.Prop8 = temp14; } } else if (defaultValueIfNotFound) @@ -154,11 +154,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop8 = instance.Prop8; } - if (TryGetConfigurationValue(configuration, key: "Prop9", out string? value8)) + if (TryGetConfigurationValue(configuration, key: "Prop9", out string? value15)) { - if (!string.IsNullOrEmpty(value8)) + if (!string.IsNullOrEmpty(value15) && TryParseLong(value15, configuration.GetSection("Prop9").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out long temp16)) { - instance.Prop9 = ParseLong(value8, configuration.GetSection("Prop9").Path); + instance.Prop9 = temp16; } } else if (defaultValueIfNotFound) @@ -166,11 +166,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop9 = instance.Prop9; } - if (TryGetConfigurationValue(configuration, key: "Prop10", out string? value9)) + if (TryGetConfigurationValue(configuration, key: "Prop10", out string? value17)) { - if (!string.IsNullOrEmpty(value9)) + if (!string.IsNullOrEmpty(value17) && TryParseFloat(value17, configuration.GetSection("Prop10").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out float temp18)) { - instance.Prop10 = ParseFloat(value9, configuration.GetSection("Prop10").Path); + instance.Prop10 = temp18; } } else if (defaultValueIfNotFound) @@ -178,11 +178,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop10 = instance.Prop10; } - if (TryGetConfigurationValue(configuration, key: "Prop13", out string? value10)) + if (TryGetConfigurationValue(configuration, key: "Prop13", out string? value19)) { - if (!string.IsNullOrEmpty(value10)) + if (!string.IsNullOrEmpty(value19) && TryParseUshort(value19, configuration.GetSection("Prop13").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out ushort temp20)) { - instance.Prop13 = ParseUshort(value10, configuration.GetSection("Prop13").Path); + instance.Prop13 = temp20; } } else if (defaultValueIfNotFound) @@ -190,11 +190,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop13 = instance.Prop13; } - if (TryGetConfigurationValue(configuration, key: "Prop14", out string? value11)) + if (TryGetConfigurationValue(configuration, key: "Prop14", out string? value21)) { - if (!string.IsNullOrEmpty(value11)) + if (!string.IsNullOrEmpty(value21) && TryParseUint(value21, configuration.GetSection("Prop14").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out uint temp22)) { - instance.Prop14 = ParseUint(value11, configuration.GetSection("Prop14").Path); + instance.Prop14 = temp22; } } else if (defaultValueIfNotFound) @@ -202,11 +202,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop14 = instance.Prop14; } - if (TryGetConfigurationValue(configuration, key: "Prop15", out string? value12)) + if (TryGetConfigurationValue(configuration, key: "Prop15", out string? value23)) { - if (!string.IsNullOrEmpty(value12)) + if (!string.IsNullOrEmpty(value23) && TryParseUlong(value23, configuration.GetSection("Prop15").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out ulong temp24)) { - instance.Prop15 = ParseUlong(value12, configuration.GetSection("Prop15").Path); + instance.Prop15 = temp24; } } else if (defaultValueIfNotFound) @@ -214,9 +214,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop15 = instance.Prop15; } - if (TryGetConfigurationValue(configuration, key: "Prop16", out string? value13)) + if (TryGetConfigurationValue(configuration, key: "Prop16", out string? value25)) { - instance.Prop16 = value13; + instance.Prop16 = value25; } else if (defaultValueIfNotFound) { @@ -227,17 +227,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop17", out string? value14)) + if (TryGetConfigurationValue(configuration, key: "Prop17", out string? value26)) { - if (value14 is null) + if (value26 is null) { instance.Prop17 = null; } else { - if (!string.IsNullOrEmpty(value14)) + if (!string.IsNullOrEmpty(value26) && TryParseSystemGlobalizationCultureInfo(value26, configuration.GetSection("Prop17").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Globalization.CultureInfo temp27)) { - instance.Prop17 = ParseSystemGlobalizationCultureInfo(value14, configuration.GetSection("Prop17").Path); + instance.Prop17 = temp27; } } } @@ -250,11 +250,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop19", out string? value15)) + if (TryGetConfigurationValue(configuration, key: "Prop19", out string? value28)) { - if (!string.IsNullOrEmpty(value15)) + if (!string.IsNullOrEmpty(value28) && TryParseSystemDateTime(value28, configuration.GetSection("Prop19").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTime temp29)) { - instance.Prop19 = ParseSystemDateTime(value15, configuration.GetSection("Prop19").Path); + instance.Prop19 = temp29; } } else if (defaultValueIfNotFound) @@ -262,11 +262,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop19 = instance.Prop19; } - if (TryGetConfigurationValue(configuration, key: "Prop20", out string? value16)) + if (TryGetConfigurationValue(configuration, key: "Prop20", out string? value30)) { - if (!string.IsNullOrEmpty(value16)) + if (!string.IsNullOrEmpty(value30) && TryParseSystemDateTimeOffset(value30, configuration.GetSection("Prop20").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTimeOffset temp31)) { - instance.Prop20 = ParseSystemDateTimeOffset(value16, configuration.GetSection("Prop20").Path); + instance.Prop20 = temp31; } } else if (defaultValueIfNotFound) @@ -274,11 +274,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop20 = instance.Prop20; } - if (TryGetConfigurationValue(configuration, key: "Prop21", out string? value17)) + if (TryGetConfigurationValue(configuration, key: "Prop21", out string? value32)) { - if (!string.IsNullOrEmpty(value17)) + if (!string.IsNullOrEmpty(value32) && TryParseDecimal(value32, configuration.GetSection("Prop21").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out decimal temp33)) { - instance.Prop21 = ParseDecimal(value17, configuration.GetSection("Prop21").Path); + instance.Prop21 = temp33; } } else if (defaultValueIfNotFound) @@ -286,11 +286,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop21 = instance.Prop21; } - if (TryGetConfigurationValue(configuration, key: "Prop23", out string? value18)) + if (TryGetConfigurationValue(configuration, key: "Prop23", out string? value34)) { - if (!string.IsNullOrEmpty(value18)) + if (!string.IsNullOrEmpty(value34) && TryParseSystemTimeSpan(value34, configuration.GetSection("Prop23").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.TimeSpan temp35)) { - instance.Prop23 = ParseSystemTimeSpan(value18, configuration.GetSection("Prop23").Path); + instance.Prop23 = temp35; } } else if (defaultValueIfNotFound) @@ -298,11 +298,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop23 = instance.Prop23; } - if (TryGetConfigurationValue(configuration, key: "Prop24", out string? value19)) + if (TryGetConfigurationValue(configuration, key: "Prop24", out string? value36)) { - if (!string.IsNullOrEmpty(value19)) + if (!string.IsNullOrEmpty(value36) && TryParseSystemGuid(value36, configuration.GetSection("Prop24").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Guid temp37)) { - instance.Prop24 = ParseSystemGuid(value19, configuration.GetSection("Prop24").Path); + instance.Prop24 = temp37; } } else if (defaultValueIfNotFound) @@ -310,17 +310,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop24 = instance.Prop24; } - if (TryGetConfigurationValue(configuration, key: "Prop25", out string? value20)) + if (TryGetConfigurationValue(configuration, key: "Prop25", out string? value38)) { - if (value20 is null) + if (value38 is null) { instance.Prop25 = null; } else { - if (!string.IsNullOrEmpty(value20)) + if (!string.IsNullOrEmpty(value38) && TryParseSystemUri(value38, configuration.GetSection("Prop25").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Uri temp39)) { - instance.Prop25 = ParseSystemUri(value20, configuration.GetSection("Prop25").Path); + instance.Prop25 = temp39; } } } @@ -333,17 +333,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop26", out string? value21)) + if (TryGetConfigurationValue(configuration, key: "Prop26", out string? value40)) { - if (value21 is null) + if (value40 is null) { instance.Prop26 = null; } else { - if (!string.IsNullOrEmpty(value21)) + if (!string.IsNullOrEmpty(value40) && TryParseSystemVersion(value40, configuration.GetSection("Prop26").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Version temp41)) { - instance.Prop26 = ParseSystemVersion(value21, configuration.GetSection("Prop26").Path); + instance.Prop26 = temp41; } } } @@ -356,11 +356,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop27", out string? value22)) + if (TryGetConfigurationValue(configuration, key: "Prop27", out string? value42)) { - if (!string.IsNullOrEmpty(value22)) + if (!string.IsNullOrEmpty(value42) && TryParseEnum(value42, configuration.GetSection("Prop27").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DayOfWeek temp43)) { - instance.Prop27 = ParseEnum(value22, configuration.GetSection("Prop27").Path); + instance.Prop27 = temp43; } } else if (defaultValueIfNotFound) @@ -368,11 +368,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop27 = instance.Prop27; } - if (TryGetConfigurationValue(configuration, key: "Prop7", out string? value23)) + if (TryGetConfigurationValue(configuration, key: "Prop7", out string? value44)) { - if (!string.IsNullOrEmpty(value23)) + if (!string.IsNullOrEmpty(value44) && TryParseSystemInt128(value44, configuration.GetSection("Prop7").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Int128 temp45)) { - instance.Prop7 = ParseSystemInt128(value23, configuration.GetSection("Prop7").Path); + instance.Prop7 = temp45; } } else if (defaultValueIfNotFound) @@ -380,11 +380,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop7 = instance.Prop7; } - if (TryGetConfigurationValue(configuration, key: "Prop11", out string? value24)) + if (TryGetConfigurationValue(configuration, key: "Prop11", out string? value46)) { - if (!string.IsNullOrEmpty(value24)) + if (!string.IsNullOrEmpty(value46) && TryParseSystemHalf(value46, configuration.GetSection("Prop11").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.Half temp47)) { - instance.Prop11 = ParseSystemHalf(value24, configuration.GetSection("Prop11").Path); + instance.Prop11 = temp47; } } else if (defaultValueIfNotFound) @@ -392,11 +392,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop11 = instance.Prop11; } - if (TryGetConfigurationValue(configuration, key: "Prop12", out string? value25)) + if (TryGetConfigurationValue(configuration, key: "Prop12", out string? value48)) { - if (!string.IsNullOrEmpty(value25)) + if (!string.IsNullOrEmpty(value48) && TryParseSystemUInt128(value48, configuration.GetSection("Prop12").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.UInt128 temp49)) { - instance.Prop12 = ParseSystemUInt128(value25, configuration.GetSection("Prop12").Path); + instance.Prop12 = temp49; } } else if (defaultValueIfNotFound) @@ -404,11 +404,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop12 = instance.Prop12; } - if (TryGetConfigurationValue(configuration, key: "Prop18", out string? value26)) + if (TryGetConfigurationValue(configuration, key: "Prop18", out string? value50)) { - if (!string.IsNullOrEmpty(value26)) + if (!string.IsNullOrEmpty(value50) && TryParseSystemDateOnly(value50, configuration.GetSection("Prop18").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateOnly temp51)) { - instance.Prop18 = ParseSystemDateOnly(value26, configuration.GetSection("Prop18").Path); + instance.Prop18 = temp51; } } else if (defaultValueIfNotFound) @@ -416,11 +416,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop18 = instance.Prop18; } - if (TryGetConfigurationValue(configuration, key: "Prop22", out string? value27)) + if (TryGetConfigurationValue(configuration, key: "Prop22", out string? value52)) { - if (!string.IsNullOrEmpty(value27)) + if (!string.IsNullOrEmpty(value52) && TryParseSystemTimeOnly(value52, configuration.GetSection("Prop22").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.TimeOnly temp53)) { - instance.Prop22 = ParseSystemTimeOnly(value27, configuration.GetSection("Prop22").Path); + instance.Prop22 = temp53; } } else if (defaultValueIfNotFound) @@ -428,21 +428,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop22 = instance.Prop22; } - if (TryGetConfigurationValue(configuration, key: "Prop28", out string? value28)) + if (TryGetConfigurationValue(configuration, key: "Prop28", out string? value54)) { - if (value28 is null) + if (value54 is null) { instance.Prop28 = null; } else { - if (value28 == string.Empty) + if (value54 == string.Empty && TryParseByteArray(value54, configuration.GetSection("Prop28").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte[] temp55)) { - instance.Prop28 = ParseByteArray(value28, configuration.GetSection("Prop28").Path); + instance.Prop28 = temp55; } - else if (!string.IsNullOrEmpty(value28)) + else if (!string.IsNullOrEmpty(value54) && TryParseByteArray(value54, configuration.GetSection("Prop28").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out byte[] temp56)) { - instance.Prop28 = ParseByteArray(value28, configuration.GetSection("Prop28").Path); + instance.Prop28 = temp56; } } } @@ -455,11 +455,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - if (TryGetConfigurationValue(configuration, key: "Prop29", out string? value29)) + if (TryGetConfigurationValue(configuration, key: "Prop29", out string? value57)) { - if (!string.IsNullOrEmpty(value29)) + if (!string.IsNullOrEmpty(value57) && TryParseInt(value57, configuration.GetSection("Prop29").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp58)) { - instance.Prop29 = ParseInt(value29, configuration.GetSection("Prop29").Path); + instance.Prop29 = temp58; } } else if (defaultValueIfNotFound) @@ -467,11 +467,11 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Prop29 = instance.Prop29; } - if (TryGetConfigurationValue(configuration, key: "Prop30", out string? value30)) + if (TryGetConfigurationValue(configuration, key: "Prop30", out string? value59)) { - if (!string.IsNullOrEmpty(value30)) + if (!string.IsNullOrEmpty(value59) && TryParseSystemDateTime(value59, configuration.GetSection("Prop30").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out global::System.DateTime temp60)) { - instance.Prop30 = ParseSystemDateTime(value30, configuration.GetSection("Prop30").Path); + instance.Prop30 = temp60; } } else if (defaultValueIfNotFound) @@ -515,11 +515,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static T ParseEnum(string value, string? path) where T : struct + public static bool TryParseEnum(string value, string? path, bool errorOnFailedBinding, out T result) where T : struct { try { - return Enum.Parse(value, ignoreCase: true); + result = Enum.Parse(value, ignoreCase: true); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -527,11 +533,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static bool ParseBool(string value, string? path) + public static bool TryParseBool(string value, string? path, bool errorOnFailedBinding, out bool result) { try { - return bool.Parse(value); + result = bool.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -539,11 +551,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static byte ParseByte(string value, string? path) + public static bool TryParseByte(string value, string? path, bool errorOnFailedBinding, out byte result) { try { - return byte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = byte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -551,11 +569,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static sbyte ParseSbyte(string value, string? path) + public static bool TryParseSbyte(string value, string? path, bool errorOnFailedBinding, out sbyte result) { try { - return sbyte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = sbyte.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -563,11 +587,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static char ParseChar(string value, string? path) + public static bool TryParseChar(string value, string? path, bool errorOnFailedBinding, out char result) { try { - return char.Parse(value); + result = char.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -575,11 +605,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static double ParseDouble(string value, string? path) + public static bool TryParseDouble(string value, string? path, bool errorOnFailedBinding, out double result) { try { - return double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -587,11 +623,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -599,11 +641,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static short ParseShort(string value, string? path) + public static bool TryParseShort(string value, string? path, bool errorOnFailedBinding, out short result) { try { - return short.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = short.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -611,11 +659,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static long ParseLong(string value, string? path) + public static bool TryParseLong(string value, string? path, bool errorOnFailedBinding, out long result) { try { - return long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -623,11 +677,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static float ParseFloat(string value, string? path) + public static bool TryParseFloat(string value, string? path, bool errorOnFailedBinding, out float result) { try { - return float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = float.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -635,11 +695,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static ushort ParseUshort(string value, string? path) + public static bool TryParseUshort(string value, string? path, bool errorOnFailedBinding, out ushort result) { try { - return ushort.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = ushort.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -647,11 +713,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static uint ParseUint(string value, string? path) + public static bool TryParseUint(string value, string? path, bool errorOnFailedBinding, out uint result) { try { - return uint.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = uint.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -659,11 +731,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static ulong ParseUlong(string value, string? path) + public static bool TryParseUlong(string value, string? path, bool errorOnFailedBinding, out ulong result) { try { - return ulong.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = ulong.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -671,11 +749,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Globalization.CultureInfo ParseSystemGlobalizationCultureInfo(string value, string? path) + public static bool TryParseSystemGlobalizationCultureInfo(string value, string? path, bool errorOnFailedBinding, out global::System.Globalization.CultureInfo result) { try { - return CultureInfo.GetCultureInfo(value); + result = CultureInfo.GetCultureInfo(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -683,11 +767,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.DateTime ParseSystemDateTime(string value, string? path) + public static bool TryParseSystemDateTime(string value, string? path, bool errorOnFailedBinding, out global::System.DateTime result) { try { - return global::System.DateTime.Parse(value, CultureInfo.InvariantCulture); + result = global::System.DateTime.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -695,11 +785,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.DateTimeOffset ParseSystemDateTimeOffset(string value, string? path) + public static bool TryParseSystemDateTimeOffset(string value, string? path, bool errorOnFailedBinding, out global::System.DateTimeOffset result) { try { - return global::System.DateTimeOffset.Parse(value, CultureInfo.InvariantCulture); + result = global::System.DateTimeOffset.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -707,11 +803,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static decimal ParseDecimal(string value, string? path) + public static bool TryParseDecimal(string value, string? path, bool errorOnFailedBinding, out decimal result) { try { - return decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + result = decimal.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -719,11 +821,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.TimeSpan ParseSystemTimeSpan(string value, string? path) + public static bool TryParseSystemTimeSpan(string value, string? path, bool errorOnFailedBinding, out global::System.TimeSpan result) { try { - return global::System.TimeSpan.Parse(value, CultureInfo.InvariantCulture); + result = global::System.TimeSpan.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -731,11 +839,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Guid ParseSystemGuid(string value, string? path) + public static bool TryParseSystemGuid(string value, string? path, bool errorOnFailedBinding, out global::System.Guid result) { try { - return global::System.Guid.Parse(value); + result = global::System.Guid.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -743,11 +857,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Uri ParseSystemUri(string value, string? path) + public static bool TryParseSystemUri(string value, string? path, bool errorOnFailedBinding, out global::System.Uri result) { try { - return new Uri(value, UriKind.RelativeOrAbsolute); + result = new Uri(value, UriKind.RelativeOrAbsolute); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -755,11 +875,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Version ParseSystemVersion(string value, string? path) + public static bool TryParseSystemVersion(string value, string? path, bool errorOnFailedBinding, out global::System.Version result) { try { - return global::System.Version.Parse(value); + result = global::System.Version.Parse(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -767,11 +893,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Int128 ParseSystemInt128(string value, string? path) + public static bool TryParseSystemInt128(string value, string? path, bool errorOnFailedBinding, out global::System.Int128 result) { try { - return global::System.Int128.Parse(value, CultureInfo.InvariantCulture); + result = global::System.Int128.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -779,11 +911,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.Half ParseSystemHalf(string value, string? path) + public static bool TryParseSystemHalf(string value, string? path, bool errorOnFailedBinding, out global::System.Half result) { try { - return global::System.Half.Parse(value, CultureInfo.InvariantCulture); + result = global::System.Half.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -791,11 +929,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.UInt128 ParseSystemUInt128(string value, string? path) + public static bool TryParseSystemUInt128(string value, string? path, bool errorOnFailedBinding, out global::System.UInt128 result) { try { - return global::System.UInt128.Parse(value, CultureInfo.InvariantCulture); + result = global::System.UInt128.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -803,11 +947,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.DateOnly ParseSystemDateOnly(string value, string? path) + public static bool TryParseSystemDateOnly(string value, string? path, bool errorOnFailedBinding, out global::System.DateOnly result) { try { - return global::System.DateOnly.Parse(value, CultureInfo.InvariantCulture); + result = global::System.DateOnly.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -815,11 +965,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static global::System.TimeOnly ParseSystemTimeOnly(string value, string? path) + public static bool TryParseSystemTimeOnly(string value, string? path, bool errorOnFailedBinding, out global::System.TimeOnly result) { try { - return global::System.TimeOnly.Parse(value, CultureInfo.InvariantCulture); + result = global::System.TimeOnly.Parse(value, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { @@ -827,11 +983,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static byte[] ParseByteArray(string value, string? path) + public static bool TryParseByteArray(string value, string? path, bool errorOnFailedBinding, out byte[] result) { try { - return Convert.FromBase64String(value); + result = Convert.FromBase64String(value); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/UnsupportedTypes.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/UnsupportedTypes.generated.txt index 3f3222a95fbffc..16c874dee7a431 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/UnsupportedTypes.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/netcoreapp/Version1/UnsupportedTypes.generated.txt @@ -139,9 +139,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (TryGetConfigurationValue(configuration, key: "Age", out string? value3)) { - if (!string.IsNullOrEmpty(value3)) + if (!string.IsNullOrEmpty(value3) && TryParseInt(value3, configuration.GetSection("Age").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp4)) { - instance.Age = ParseInt(value3, configuration.GetSection("Age").Path); + instance.Age = temp4; } } else if (defaultValueIfNotFound) @@ -149,43 +149,43 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration instance.Age = instance.Age; } - var value4 = configuration.GetSection("List"); - if (AsConfigWithChildren(value4) is IConfigurationSection section5) + var value5 = configuration.GetSection("List"); + if (AsConfigWithChildren(value5) is IConfigurationSection section6) { - global::System.Collections.Generic.List? temp7 = instance.List; - temp7 ??= new global::System.Collections.Generic.List(); - BindCore(section5, ref temp7, defaultValueIfNotFound: false, binderOptions); - instance.List = temp7; + global::System.Collections.Generic.List? temp8 = instance.List; + temp8 ??= new global::System.Collections.Generic.List(); + BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions); + instance.List = temp8; } else { instance.List = instance.List; } - var value8 = configuration.GetSection("Array"); - if (AsConfigWithChildren(value8) is IConfigurationSection section9) + var value9 = configuration.GetSection("Array"); + if (AsConfigWithChildren(value9) is IConfigurationSection section10) { - string[]? temp11 = instance.Array; - temp11 ??= new string[0]; - BindCore(section9, ref temp11, defaultValueIfNotFound: false, binderOptions); - instance.Array = temp11; + string[]? temp12 = instance.Array; + temp12 ??= new string[0]; + BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions); + instance.Array = temp12; } else { instance.Array = instance.Array; } - if (instance.Array is null && TryGetConfigurationValue(value8, key: null, out string? value12) && value12 == string.Empty) + if (instance.Array is null && TryGetConfigurationValue(value9, key: null, out string? value13) && value13 == string.Empty) { instance.Array = global::System.Array.Empty(); } - var value13 = configuration.GetSection("Record"); - if (AsConfigWithChildren(value13) is IConfigurationSection section14) + var value14 = configuration.GetSection("Record"); + if (AsConfigWithChildren(value14) is IConfigurationSection section15) { - global::Record? temp16 = instance.Record; - temp16 ??= InitializeRecord___System__Action___(section14, binderOptions); - BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions); - instance.Record = temp16; + global::Record? temp17 = instance.Record; + temp17 ??= InitializeRecord___System__Action___(section15, binderOptions); + BindCore(section15, ref temp17, defaultValueIfNotFound: false, binderOptions); + instance.Record = temp17; } else { @@ -196,9 +196,9 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration public static global::Record InitializeRecord___System__Action___(IConfiguration configuration, BinderOptions? binderOptions) { int x = (int)(10); - if (TryGetConfigurationValue(configuration, key: "x", out string? value17) && value17 is not null) + if (TryGetConfigurationValue(configuration, key: "x", out string? value18) && value18 is not null && TryParseInt(value18, configuration.GetSection("x").Path, binderOptions?.ErrorOnUnknownConfiguration is true, out int temp19)) { - x = ParseInt(value17, configuration.GetSection("x").Path); + x = temp19; } return new global::Record(x) @@ -278,11 +278,17 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return binderOptions; } - public static int ParseInt(string value, string? path) + public static bool TryParseInt(string value, string? path, bool errorOnFailedBinding, out int result) { try { - return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + result = int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture); + return true; + } + catch when (!errorOnFailedBinding) + { + result = default; + return false; } catch (Exception exception) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs index eef0a38bf22535..183ea0040ce588 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs @@ -165,7 +165,7 @@ private static async Task VerifyAgainstBaselineUsingF IEnumerable lines = resultSourceText.Lines.Select(l => l.ToString()); string source = string.Join(Environment.NewLine, lines).TrimEnd(Environment.NewLine.ToCharArray()) + Environment.NewLine; - path = Path.Combine($"{repoRootDir}\\src\\libraries\\Microsoft.Extensions.Configuration.Binder\\tests\\SourceGenerationTests\\", path); + path = Path.Combine(repoRootDir, "src", "libraries", "Microsoft.Extensions.Configuration.Binder", "tests", "SourceGenerationTests", path); #if NET await File.WriteAllTextAsync(path, source);