Skip to content

Commit c79c8e1

Browse files
authored
Allow access to child providers in ChainedConfigurationProvider (#67610)
1 parent 548bb58 commit c79c8e1

File tree

4 files changed

+71
-7
lines changed

4 files changed

+71
-7
lines changed

src/libraries/Microsoft.Extensions.Configuration/ref/Microsoft.Extensions.Configuration.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public static partial class ChainedBuilderExtensions
1414
public partial class ChainedConfigurationProvider : Microsoft.Extensions.Configuration.IConfigurationProvider, System.IDisposable
1515
{
1616
public ChainedConfigurationProvider(Microsoft.Extensions.Configuration.ChainedConfigurationSource source) { }
17+
public Microsoft.Extensions.Configuration.IConfiguration Configuration { get { throw null; } }
1718
public void Dispose() { }
1819
public System.Collections.Generic.IEnumerable<string> GetChildKeys(System.Collections.Generic.IEnumerable<string> earlierKeys, string? parentPath) { throw null; }
1920
public Microsoft.Extensions.Primitives.IChangeToken GetReloadToken() { throw null; }

src/libraries/Microsoft.Extensions.Configuration/src/ChainedConfigurationProvider.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ public class ChainedConfigurationProvider : IConfigurationProvider, IDisposable
2121
/// <param name="source">The source configuration.</param>
2222
public ChainedConfigurationProvider(ChainedConfigurationSource source!!)
2323
{
24-
if (source.Configuration == null)
25-
{
26-
throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "source.Configuration"), nameof(source));
27-
}
28-
29-
_config = source.Configuration;
24+
_config = source.Configuration ?? throw new ArgumentException(SR.Format(SR.InvalidNullArgument, "source.Configuration"), nameof(source));
3025
_shouldDisposeConfig = source.ShouldDisposeConfiguration;
3126
}
3227

28+
/// <summary>
29+
/// Gets the chained configuration.
30+
/// </summary>
31+
public IConfiguration Configuration => _config;
32+
3333
/// <summary>
3434
/// Tries to get a configuration value for the specified key.
3535
/// </summary>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using Microsoft.Extensions.Configuration.Memory;
7+
using Xunit;
8+
9+
namespace Microsoft.Extensions.Configuration.Test
10+
{
11+
public class ChainedConfigurationProvierTests
12+
{
13+
[Fact]
14+
public void ChainedConfiguration_UsingMemoryConfigurationSource_ChainedCouldExposeProvider()
15+
{
16+
var chainedConfigurationProvider = new ChainedConfigurationSource
17+
{
18+
Configuration = new ConfigurationBuilder()
19+
.Add(new MemoryConfigurationSource {
20+
InitialData = new Dictionary<string, string>() { { "a:b", "c" } }
21+
})
22+
.Build(),
23+
ShouldDisposeConfiguration = false,
24+
}
25+
.Build(new ConfigurationBuilder()) as ChainedConfigurationProvider;
26+
27+
Assert.True(chainedConfigurationProvider.TryGet("a:b", out string? value));
28+
Assert.Equal("c", value);
29+
Assert.Equal("c", chainedConfigurationProvider.Configuration["a:b"]);
30+
31+
var configRoot = chainedConfigurationProvider.Configuration as IConfigurationRoot;
32+
Assert.NotNull(configRoot);
33+
Assert.Equal(1, configRoot.Providers.Count());
34+
Assert.IsType<MemoryConfigurationProvider>(configRoot.Providers.First());
35+
}
36+
37+
[Fact]
38+
public void ChainedConfiguration_ExposesProvider()
39+
{
40+
var providers = new IConfigurationProvider[] {
41+
new TestConfigurationProvider("foo", "foo-value")
42+
};
43+
var chainedConfigurationSource = new ChainedConfigurationSource
44+
{
45+
Configuration = new ConfigurationRoot(providers),
46+
ShouldDisposeConfiguration = false,
47+
};
48+
49+
var chainedConfigurationProvider = chainedConfigurationSource
50+
.Build(new ConfigurationBuilder()) as ChainedConfigurationProvider;
51+
52+
var configRoot = chainedConfigurationProvider.Configuration as IConfigurationRoot;
53+
Assert.NotNull(configRoot);
54+
Assert.Equal(providers, configRoot.Providers);
55+
}
56+
57+
private class TestConfigurationProvider : ConfigurationProvider
58+
{
59+
public TestConfigurationProvider(string key, string value)
60+
=> Data.Add(key, value);
61+
}
62+
}
63+
}

src/libraries/Microsoft.Extensions.Configuration/tests/ConfigurationManagerTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ public async Task ProviderDisposeDelayedWaitingOnConcurrentRead(Action<IConfigur
221221

222222
builder.Add(new TestConfigurationSource(provider));
223223

224-
// Reading configuration will block on provider.TryRead() or profvider.GetChildKeys().
224+
// Reading configuration will block on provider.TryRead() or provider.GetChildKeys().
225225
var readTask = Task.Run(() => concurrentReadAction(config));
226226
await provider.ReadStartedTask;
227227

0 commit comments

Comments
 (0)