diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs index fcfeece70f7b7b..63631499653f25 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs @@ -124,6 +124,10 @@ private void EmitBindLogicFromString( { parsedValueExpr = stringValueToParse_Expr; } + else if (typeKind is StringParsableTypeKind.Enum) + { + parsedValueExpr = $"ParseEnum<{type.MinimalDisplayString}>({stringValueToParse_Expr}, () => {sectionPathExpr})"; + } else { string helperMethodDisplayString = GetHelperMethodDisplayString(type.ParseMethodName); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/CoreBindingHelper.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/CoreBindingHelper.cs index bcd4195c192bb7..3d38f83aea4f10 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/CoreBindingHelper.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/Emitter/CoreBindingHelper.cs @@ -429,10 +429,24 @@ private void EmitHelperMethods() _emitBlankLineBeforeNextStatement = true; } + bool enumTypeExists = false; + foreach (ParsableFromStringSpec type in _sourceGenSpec.PrimitivesForHelperGen) { EmitBlankLineIfRequired(); - EmitPrimitiveParseMethod(type); + + if (type.StringParsableTypeKind == StringParsableTypeKind.Enum) + { + if (!enumTypeExists) + { + EmitEnumParseMethod(); + enumTypeExists = true; + } + } + else + { + EmitPrimitiveParseMethod(type); + } } } @@ -518,6 +532,30 @@ private void EmitGetBinderOptionsHelper() """); } + private void EmitEnumParseMethod() + { + string innerExceptionTypeDisplayString = _useFullyQualifiedNames ? "global::System.Exception" : "Exception"; + string exceptionArg1 = string.Format(ExceptionMessages.FailedBinding, $"{{{Identifier.getPath}()}}", $"{{typeof(T)}}"); + + _writer.WriteLine($$""" + public static T ParseEnum(string value, Func getPath) where T : struct + { + try + { + #if NETFRAMEWORK || NETSTANDARD2_0 + return (T)Enum.Parse(typeof(T), value, ignoreCase: true); + #else + return Enum.Parse(value, ignoreCase: true); + #endif + } + catch ({{innerExceptionTypeDisplayString}} {{Identifier.exception}}) + { + throw new {{GetInvalidOperationDisplayName()}}($"{{exceptionArg1}}", {{Identifier.exception}}); + } + } + """); + } + private void EmitPrimitiveParseMethod(ParsableFromStringSpec type) { string innerExceptionTypeDisplayString; @@ -546,10 +584,7 @@ private void EmitPrimitiveParseMethod(ParsableFromStringSpec type) switch (typeKind) { case StringParsableTypeKind.Enum: - { - parsedValueExpr = $"({typeDisplayString}){Identifier.Enum}.{Identifier.Parse}(typeof({typeDisplayString}), {Identifier.value}, ignoreCase: true)"; - } - break; + return; case StringParsableTypeKind.ByteArray: { parsedValueExpr = $"Convert.FromBase64String({Identifier.value})"; diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Primitives.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Primitives.generated.txt index 24321361757019..5d30288a21e785 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Primitives.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Primitives.generated.txt @@ -139,7 +139,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration if (configuration["Prop27"] is string value22) { - obj.Prop27 = ParseDayOfWeek(value22, () => configuration.GetSection("Prop27").Path); + obj.Prop27 = ParseEnum(value22, () => configuration.GetSection("Prop27").Path); } if (configuration["Prop7"] is string value23) @@ -430,15 +430,19 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration } } - public static DayOfWeek ParseDayOfWeek(string value, Func getPath) + public static T ParseEnum(string value, Func getPath) where T : struct { try { - return (DayOfWeek)Enum.Parse(typeof(DayOfWeek), value, ignoreCase: true); + #if NETFRAMEWORK || NETSTANDARD2_0 + return (T)Enum.Parse(typeof(T), value, ignoreCase: true); + #else + return Enum.Parse(value, ignoreCase: true); + #endif } catch (Exception exception) { - throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(DayOfWeek)}'.", exception); + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(T)}'.", exception); } }