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"]);