From 73bb89cb7274b8c8e72a46e8c51fef31a5594039 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:44:31 +0000 Subject: [PATCH 1/7] Initial plan From 934b6e72d71bb5048394b243e43305606ce68679 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 15:24:42 +0000 Subject: [PATCH 2/7] Support IConfiguration as a bindable property type in ConfigurationBinder Co-authored-by: svick <287848+svick@users.noreply.github.com> --- .../ConfigurationBindingGenerator.Parser.cs | 4 + .../gen/Emitter/CoreBindingHelpers.cs | 11 +- .../gen/Specs/Types/SimpleTypeSpec.cs | 5 + .../src/ConfigurationBinder.cs | 4 +- .../ConfigurationBinderTests.TestClasses.cs | 10 ++ .../tests/Common/ConfigurationBinderTests.cs | 119 ++++++++++++++++++ 6 files changed, 148 insertions(+), 5 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs index beb45cff274be5..36b5e01ff42b07 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs @@ -203,6 +203,10 @@ private TypeSpec CreateTypeSpec(TypeParseInfo typeParseInfo) { spec = new ConfigurationSectionSpec(type); } + else if (SymbolEqualityComparer.Default.Equals(type, _typeSymbols.IConfiguration)) + { + spec = new ConfigurationSectionSpec(type) { IsIConfiguration = true }; + } else if (type is INamedTypeSymbol) { spec = CreateObjectSpec(typeParseInfo); 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 42979bf896c101..638c9aed0f0554 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs @@ -114,7 +114,7 @@ private void EmitGetCoreMethod() { case ParsableFromStringSpec stringParsableType: { - EmitCastToIConfigurationSection(); + EmitCastToIConfigurationSectionOrThrow(); EmitStartBlock($"if ({Identifier.TryGetConfigurationValue}({Identifier.configuration}, {Identifier.key}: null, out string? {Identifier.value}))"); EmitBindingLogic( @@ -126,9 +126,14 @@ private void EmitGetCoreMethod() EmitEndBlock(); // End if-check for input type. } break; + case ConfigurationSectionSpec { IsIConfiguration: true }: + { + _writer.WriteLine($"return {Identifier.configuration};"); + } + break; case ConfigurationSectionSpec: { - EmitCastToIConfigurationSection(); + EmitCastToIConfigurationSectionOrThrow(); _writer.WriteLine($"return {Identifier.section};"); } break; @@ -161,7 +166,7 @@ private void EmitGetCoreMethod() EmitEndBlock(); _emitBlankLineBeforeNextStatement = true; - void EmitCastToIConfigurationSection() => + void EmitCastToIConfigurationSectionOrThrow() => _writer.WriteLine($$""" if ({{Identifier.configuration}} is not {{Identifier.IConfigurationSection}} {{Identifier.section}}) { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/Types/SimpleTypeSpec.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/Types/SimpleTypeSpec.cs index 70c7a8042e0359..6171e387c9b28e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/Types/SimpleTypeSpec.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Specs/Types/SimpleTypeSpec.cs @@ -13,6 +13,11 @@ public SimpleTypeSpec(ITypeSymbol type) : base(type) { } internal sealed record ConfigurationSectionSpec : SimpleTypeSpec { public ConfigurationSectionSpec(ITypeSymbol type) : base(type) { } + + /// + /// Indicates whether this spec represents (as opposed to ). + /// + public bool IsIConfiguration { get; init; } } public sealed record ParsableFromStringSpec : SimpleTypeSpec diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs index 8166b108da3f31..eb1b9c50da0997 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs @@ -324,8 +324,8 @@ private static void BindInstance( BinderOptions options, bool isParentCollection) { - // if binding IConfigurationSection, break early - if (type == typeof(IConfigurationSection)) + // if binding IConfigurationSection or IConfiguration, break early + if (type == typeof(IConfigurationSection) || type == typeof(IConfiguration)) { bindingPoint.TrySetValue(config); return; 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 78f7cc9e27a554..be1a862824c2fe 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 @@ -65,11 +65,21 @@ public class ConfigurationInterfaceOptions public IConfigurationSection Section { get; set; } } + public class ConfigurationIConfigurationOptions + { + public IConfiguration Section { get; set; } + } + public class DerivedOptionsWithIConfigurationSection : DerivedOptions { public IConfigurationSection DerivedSection { get; set; } } + public class DerivedOptionsWithIConfiguration : DerivedOptions + { + public IConfiguration DerivedSection { get; set; } + } + public record struct RecordStructTypeOptions(string Color, int Length); public record RecordOptionsWithNesting(int Number, RecordOptionsWithNesting.RecordNestedOptions Nested1, 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 15514263abea49..7745c2ecad14e9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs @@ -124,6 +124,87 @@ void Test() } } + [Fact] + public void CanBindIConfiguration() + { + var dic = new Dictionary + { + {"Section:Integer", "-2"}, + {"Section:Boolean", "TRUe"}, + {"Section:Nested:Integer", "11"}, + {"Section:Virtual", "Sup"} + }; + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddInMemoryCollection(dic); + var config = configurationBuilder.Build(); + + var options = config.Get(); + var childOptions = options.Section.Get(); + Test(); + + options = (ConfigurationIConfigurationOptions)config.Get(typeof(ConfigurationIConfigurationOptions)); + childOptions = (DerivedOptions)options.Section.Get(typeof(DerivedOptions)); + Test(); + + options = config.Get(options => { }); + childOptions = options.Section.Get(options => { }); + Test(); + + options = (ConfigurationIConfigurationOptions)config.Get(typeof(ConfigurationIConfigurationOptions), options => { }); + childOptions = (DerivedOptions)options.Section.Get(typeof(DerivedOptions), options => { }); + Test(); + + void Test() + { + Assert.True(childOptions.Boolean); + Assert.Equal(-2, childOptions.Integer); + Assert.Equal(11, childOptions.Nested.Integer); + Assert.Equal("Derived:Sup", childOptions.Virtual); + + var section = Assert.IsAssignableFrom(options.Section); + Assert.Equal("Section", section.Key); + Assert.Equal("Section", section.Path); + Assert.Null(section.Value); + } + } + + [Fact] + public void CanBindIConfigurationWithDerivedOptionsSection() + { + var dic = new Dictionary + { + {"Section:Integer", "-2"}, + {"Section:Boolean", "TRUe"}, + {"Section:Nested:Integer", "11"}, + {"Section:Virtual", "Sup"}, + {"Section:DerivedSection:Nested:Integer", "11"}, + {"Section:DerivedSection:Virtual", "Sup"} + }; + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddInMemoryCollection(dic); + var config = configurationBuilder.Build(); + + var options = config.Get(); + var childOptions = options.Section.Get(); + var childDerivedOptions = childOptions.DerivedSection.Get(); + + Assert.True(childOptions.Boolean); + Assert.Equal(-2, childOptions.Integer); + Assert.Equal(11, childOptions.Nested.Integer); + Assert.Equal("Derived:Sup", childOptions.Virtual); + Assert.Equal(11, childDerivedOptions.Nested.Integer); + Assert.Equal("Derived:Sup", childDerivedOptions.Virtual); + + var section = Assert.IsAssignableFrom(options.Section); + Assert.Equal("Section", section.Key); + Assert.Equal("Section", section.Path); + + var derivedSection = Assert.IsAssignableFrom(childOptions.DerivedSection); + Assert.Equal("DerivedSection", derivedSection.Key); + Assert.Equal("Section:DerivedSection", derivedSection.Path); + Assert.Null(section.Value); + } + [Fact] public void CanBindWithKeyOverload() { @@ -2649,6 +2730,44 @@ static void ValidateList(List list) } } + [Fact] + public void GetIConfiguration() + { + var configuration = TestHelpers.GetConfigurationFromJsonString(""" + { + "vaLue": "MyString", + } + """); + + var obj = configuration.GetSection("value").Get(); + var section = Assert.IsAssignableFrom(obj); + Assert.Equal("MyString", section.Value); + + configuration = TestHelpers.GetConfigurationFromJsonString(""" + { + "vaLue": [ "MyString", { "nested": "value" } ], + } + """); + + var list = configuration.GetSection("value").Get>(); + ValidateList(list); + + var dict = configuration.Get>>(); + Assert.Equal(1, dict.Count); + ValidateList(dict["vaLue"]); + + static void ValidateList(List list) + { + Assert.Equal(2, list.Count); + Assert.Equal("0", Assert.IsAssignableFrom(list[0]).Key); + Assert.Equal("MyString", Assert.IsAssignableFrom(list[0]).Value); + + Assert.Equal("1", Assert.IsAssignableFrom(list[1]).Key); + var nestedSection = Assert.IsAssignableFrom(list[1].GetSection("nested")); + Assert.Equal("value", nestedSection.Value); + } + } + [Fact] public void NullableDictKeys() { From fada3ab526119d7594b466913126fd271bc08861 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:24:28 +0000 Subject: [PATCH 3/7] Update GetIConfiguration test to use only IConfiguration members, no IConfigurationSection casts Co-authored-by: svick <287848+svick@users.noreply.github.com> --- .../tests/Common/ConfigurationBinderTests.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) 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 7745c2ecad14e9..0b8752a73d04b5 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs @@ -2740,8 +2740,7 @@ public void GetIConfiguration() """); var obj = configuration.GetSection("value").Get(); - var section = Assert.IsAssignableFrom(obj); - Assert.Equal("MyString", section.Value); + Assert.NotNull(obj); configuration = TestHelpers.GetConfigurationFromJsonString(""" { @@ -2759,12 +2758,8 @@ public void GetIConfiguration() static void ValidateList(List list) { Assert.Equal(2, list.Count); - Assert.Equal("0", Assert.IsAssignableFrom(list[0]).Key); - Assert.Equal("MyString", Assert.IsAssignableFrom(list[0]).Value); - - Assert.Equal("1", Assert.IsAssignableFrom(list[1]).Key); - var nestedSection = Assert.IsAssignableFrom(list[1].GetSection("nested")); - Assert.Equal("value", nestedSection.Value); + Assert.Empty(list[0].GetChildren()); + Assert.Equal("value", list[1]["nested"]); } } From 1d127042648001c3d4fa27c0b05b221f78dff1a9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 18 Mar 2026 10:50:18 +0000 Subject: [PATCH 4/7] Expand GetIConfiguration test to more thoroughly verify IConfiguration binding Co-authored-by: svick <287848+svick@users.noreply.github.com> --- .../tests/Common/ConfigurationBinderTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 0b8752a73d04b5..8ec1fef4c1a577 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs @@ -2735,16 +2735,16 @@ public void GetIConfiguration() { var configuration = TestHelpers.GetConfigurationFromJsonString(""" { - "vaLue": "MyString", + "vaLue": { "key": "MyString" }, } """); var obj = configuration.GetSection("value").Get(); - Assert.NotNull(obj); + Assert.Equal("MyString", obj["key"]); configuration = TestHelpers.GetConfigurationFromJsonString(""" { - "vaLue": [ "MyString", { "nested": "value" } ], + "vaLue": [ { "key": "MyString" }, { "nested": "value" } ], } """); @@ -2758,7 +2758,7 @@ public void GetIConfiguration() static void ValidateList(List list) { Assert.Equal(2, list.Count); - Assert.Empty(list[0].GetChildren()); + Assert.Equal("MyString", list[0]["key"]); Assert.Equal("value", list[1]["nested"]); } } From d9c5d164161bc4db82e8c579ff36a2103287114c Mon Sep 17 00:00:00 2001 From: Petr Onderka Date: Wed, 18 Mar 2026 15:10:07 +0100 Subject: [PATCH 5/7] Small test improvements --- .../ConfigurationBinderTests.TestClasses.cs | 4 +- .../tests/Common/ConfigurationBinderTests.cs | 95 +++++++++---------- 2 files changed, 49 insertions(+), 50 deletions(-) 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 be1a862824c2fe..1fbb3a7ef9172d 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 @@ -60,12 +60,12 @@ public class NestedOptions } } - public class ConfigurationInterfaceOptions + public class OptionsWithIConfigurationSection { public IConfigurationSection Section { get; set; } } - public class ConfigurationIConfigurationOptions + public class OptionsWithIConfiguration { public IConfiguration Section { get; set; } } 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 8ec1fef4c1a577..2d1ab50d37a0a5 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs @@ -95,19 +95,19 @@ public void CanBindIConfigurationSection() configurationBuilder.AddInMemoryCollection(dic); var config = configurationBuilder.Build(); - var options = config.Get(); + var options = config.Get(); var childOptions = options.Section.Get(); Test(); - options = (ConfigurationInterfaceOptions)config.Get(typeof(ConfigurationInterfaceOptions)); + options = (OptionsWithIConfigurationSection)config.Get(typeof(OptionsWithIConfigurationSection)); childOptions = (DerivedOptions)options.Section.Get(typeof(DerivedOptions)); Test(); - options = config.Get(options => { }); + options = config.Get(options => { }); childOptions = options.Section.Get(options => { }); Test(); - options = (ConfigurationInterfaceOptions)config.Get(typeof(ConfigurationInterfaceOptions), options => { }); + options = (OptionsWithIConfigurationSection)config.Get(typeof(OptionsWithIConfigurationSection), options => { }); childOptions = (DerivedOptions)options.Section.Get(typeof(DerivedOptions), options => { }); Test(); @@ -124,6 +124,42 @@ void Test() } } + [Fact] + public void CanBindIConfigurationSectionWithDerivedOptionsSection() + { + var dic = new Dictionary + { + {"Section:Integer", "-2"}, + {"Section:Boolean", "TRUe"}, + {"Section:Nested:Integer", "11"}, + {"Section:Virtual", "Sup"}, + {"Section:DerivedSection:Nested:Integer", "11"}, + {"Section:DerivedSection:Virtual", "Sup"} + }; + var configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.AddInMemoryCollection(dic); + var config = configurationBuilder.Build(); + + var options = config.Get(); + + var childOptions = options.Section.Get(); + + var childDerivedOptions = childOptions.DerivedSection.Get(); + + Assert.True(childOptions.Boolean); + Assert.Equal(-2, childOptions.Integer); + Assert.Equal(11, childOptions.Nested.Integer); + Assert.Equal("Derived:Sup", childOptions.Virtual); + Assert.Equal(11, childDerivedOptions.Nested.Integer); + Assert.Equal("Derived:Sup", childDerivedOptions.Virtual); + + Assert.Equal("Section", options.Section.Key); + Assert.Equal("Section", options.Section.Path); + Assert.Equal("DerivedSection", childOptions.DerivedSection.Key); + Assert.Equal("Section:DerivedSection", childOptions.DerivedSection.Path); + Assert.Null(options.Section.Value); + } + [Fact] public void CanBindIConfiguration() { @@ -138,19 +174,19 @@ public void CanBindIConfiguration() configurationBuilder.AddInMemoryCollection(dic); var config = configurationBuilder.Build(); - var options = config.Get(); + var options = config.Get(); var childOptions = options.Section.Get(); Test(); - options = (ConfigurationIConfigurationOptions)config.Get(typeof(ConfigurationIConfigurationOptions)); + options = (OptionsWithIConfiguration)config.Get(typeof(OptionsWithIConfiguration)); childOptions = (DerivedOptions)options.Section.Get(typeof(DerivedOptions)); Test(); - options = config.Get(options => { }); + options = config.Get(options => { }); childOptions = options.Section.Get(options => { }); Test(); - options = (ConfigurationIConfigurationOptions)config.Get(typeof(ConfigurationIConfigurationOptions), options => { }); + options = (OptionsWithIConfiguration)config.Get(typeof(OptionsWithIConfiguration), options => { }); childOptions = (DerivedOptions)options.Section.Get(typeof(DerivedOptions), options => { }); Test(); @@ -184,7 +220,7 @@ public void CanBindIConfigurationWithDerivedOptionsSection() configurationBuilder.AddInMemoryCollection(dic); var config = configurationBuilder.Build(); - var options = config.Get(); + var options = config.Get(); var childOptions = options.Section.Get(); var childDerivedOptions = childOptions.DerivedSection.Get(); @@ -228,42 +264,6 @@ public void CanBindWithKeyOverload() Assert.Equal("Derived:Sup", options.Virtual); } - [Fact] - public void CanBindIConfigurationSectionWithDerivedOptionsSection() - { - var dic = new Dictionary - { - {"Section:Integer", "-2"}, - {"Section:Boolean", "TRUe"}, - {"Section:Nested:Integer", "11"}, - {"Section:Virtual", "Sup"}, - {"Section:DerivedSection:Nested:Integer", "11"}, - {"Section:DerivedSection:Virtual", "Sup"} - }; - var configurationBuilder = new ConfigurationBuilder(); - configurationBuilder.AddInMemoryCollection(dic); - var config = configurationBuilder.Build(); - - var options = config.Get(); - - var childOptions = options.Section.Get(); - - var childDerivedOptions = childOptions.DerivedSection.Get(); - - Assert.True(childOptions.Boolean); - Assert.Equal(-2, childOptions.Integer); - Assert.Equal(11, childOptions.Nested.Integer); - Assert.Equal("Derived:Sup", childOptions.Virtual); - Assert.Equal(11, childDerivedOptions.Nested.Integer); - Assert.Equal("Derived:Sup", childDerivedOptions.Virtual); - - Assert.Equal("Section", options.Section.Key); - Assert.Equal("Section", options.Section.Path); - Assert.Equal("DerivedSection", childOptions.DerivedSection.Key); - Assert.Equal("Section:DerivedSection", childOptions.DerivedSection.Path); - Assert.Null(options.Section.Value); - } - [Fact] public void CanBindConfigurationKeyNameAttributes() { @@ -2744,7 +2744,7 @@ public void GetIConfiguration() configuration = TestHelpers.GetConfigurationFromJsonString(""" { - "vaLue": [ { "key": "MyString" }, { "nested": "value" } ], + "vaLue": [ { "key": "MyString" } ], } """); @@ -2757,9 +2757,8 @@ public void GetIConfiguration() static void ValidateList(List list) { - Assert.Equal(2, list.Count); + Assert.Equal(1, list.Count); Assert.Equal("MyString", list[0]["key"]); - Assert.Equal("value", list[1]["nested"]); } } From 6b1efd002c1b7b4e8ca7951bdb408afd5f48109c Mon Sep 17 00:00:00 2001 From: Petr Onderka Date: Wed, 18 Mar 2026 16:06:46 +0100 Subject: [PATCH 6/7] Rename EmitCastToIConfigurationSection back. --- .../gen/Emitter/CoreBindingHelpers.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 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 638c9aed0f0554..a4176e76233e45 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs @@ -114,7 +114,7 @@ private void EmitGetCoreMethod() { case ParsableFromStringSpec stringParsableType: { - EmitCastToIConfigurationSectionOrThrow(); + EmitCastToIConfigurationSection(); EmitStartBlock($"if ({Identifier.TryGetConfigurationValue}({Identifier.configuration}, {Identifier.key}: null, out string? {Identifier.value}))"); EmitBindingLogic( @@ -133,7 +133,7 @@ private void EmitGetCoreMethod() break; case ConfigurationSectionSpec: { - EmitCastToIConfigurationSectionOrThrow(); + EmitCastToIConfigurationSection(); _writer.WriteLine($"return {Identifier.section};"); } break; @@ -166,7 +166,7 @@ private void EmitGetCoreMethod() EmitEndBlock(); _emitBlankLineBeforeNextStatement = true; - void EmitCastToIConfigurationSectionOrThrow() => + void EmitCastToIConfigurationSection() => _writer.WriteLine($$""" if ({{Identifier.configuration}} is not {{Identifier.IConfigurationSection}} {{Identifier.section}}) { From 54f86bd2e3b76e278492b5be5ab58a8156a1cf8b Mon Sep 17 00:00:00 2001 From: Petr Onderka Date: Thu, 19 Mar 2026 11:23:46 +0100 Subject: [PATCH 7/7] Added tests for configuration.Get() --- .../tests/Common/ConfigurationBinderTests.cs | 4 ++++ 1 file changed, 4 insertions(+) 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 2d1ab50d37a0a5..d5dbe20ae7516b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs @@ -2702,6 +2702,8 @@ public void GetIConfigurationSection() } """); + Assert.Throws(() => configuration.Get()); + var obj = configuration.GetSection("value").Get(); Assert.Equal("MyString", obj.Value); @@ -2739,6 +2741,8 @@ public void GetIConfiguration() } """); + Assert.Same(configuration, configuration.Get()); + var obj = configuration.GetSection("value").Get(); Assert.Equal("MyString", obj["key"]);