diff --git a/src/Config.Tests/ConfigurationTests.cs b/src/Config.Tests/ConfigurationTests.cs
index 784a9ba..5eb5e58 100644
--- a/src/Config.Tests/ConfigurationTests.cs
+++ b/src/Config.Tests/ConfigurationTests.cs
@@ -1,5 +1,8 @@
-using System.Globalization;
+using System;
+using System.Globalization;
using System.IO;
+using System.Reflection;
+using System.Runtime.CompilerServices;
using Microsoft.Extensions.Configuration;
using Xunit;
using Xunit.Abstractions;
@@ -15,33 +18,50 @@ public ConfigurationTests(ITestOutputHelper output)
Config.GlobalLocation = Path.Combine(Constants.CurrentDirectory, "Content", "global.netconfig");
Config.SystemLocation = Path.Combine(Constants.CurrentDirectory, "Content", "system.netconfig");
CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
- Directory.SetCurrentDirectory(Path.Combine(Constants.CurrentDirectory, "Content", "web"));
this.output = output;
}
- [FlakyFact]
+ [Fact]
public void can_load_hierarchical_values()
{
- var config = new ConfigurationBuilder().AddDotNetConfig().Build();
+ var config = BuildConfiguration();
+
Assert.Equal("on", config["core:parent"]);
Assert.Equal("true", config["http:sslVerify"]);
Assert.Equal("false", config["http:https://weak.example.com:sslVerify"]);
Assert.Equal("yay", config["foo:bar:baz"]);
}
- [FlakyFact]
+ [Fact]
public void can_save_values()
{
- var config = new ConfigurationBuilder().AddDotNetConfig().Build();
+ var config = BuildConfiguration();
+
config["foo:enabled"] = "true";
config["foo:bar:baz"] = "bye";
config["http:https://weaker.example.com:sslVerify"] = "false";
- var dotnet = Config.Build();
+ var dotnet = Config.Build(Path.Combine(Constants.CurrentDirectory, "Content", "web", nameof(can_save_values)));
Assert.Equal("true", dotnet.GetString("foo", "enabled"));
Assert.Equal("bye", dotnet.GetString("foo", "bar", "baz"));
Assert.Equal("false", dotnet.GetString("http", "https://weaker.example.com", "sslVerify"));
}
+
+ [Fact]
+ public void local_values_override_system_values()
+ {
+ var config = BuildConfiguration();
+
+ Assert.Equal("123", config["local:value"]);
+ }
+
+ IConfiguration BuildConfiguration([CallerMemberName] string? methodName = null)
+ {
+ var dir = Path.Combine(Constants.CurrentDirectory, "Content", "web", methodName);
+ Directory.CreateDirectory(dir);
+
+ return new ConfigurationBuilder().AddDotNetConfig(dir).Build();
+ }
}
}
\ No newline at end of file
diff --git a/src/Config.Tests/Content/global.netconfig b/src/Config.Tests/Content/global.netconfig
index 2adff22..458ffc7 100644
--- a/src/Config.Tests/Content/global.netconfig
+++ b/src/Config.Tests/Content/global.netconfig
@@ -2,3 +2,5 @@
sslVerify = false
[core]
global = yes
+[local]
+ value = 456
\ No newline at end of file
diff --git a/src/Config.Tests/Content/web/.netconfig b/src/Config.Tests/Content/web/.netconfig
index 5f28270..54f9119 100644
--- a/src/Config.Tests/Content/web/.netconfig
+++ b/src/Config.Tests/Content/web/.netconfig
@@ -1 +1,2 @@
-
\ No newline at end of file
+[local]
+ value = 123
\ No newline at end of file
diff --git a/src/Configuration/DotNetConfigExtensions.cs b/src/Configuration/DotNetConfigExtensions.cs
index 53c5366..d140179 100644
--- a/src/Configuration/DotNetConfigExtensions.cs
+++ b/src/Configuration/DotNetConfigExtensions.cs
@@ -22,6 +22,25 @@ public static class DotNetConfigExtensions
///
///
public static IConfigurationBuilder AddDotNetConfig(this IConfigurationBuilder builder)
- => builder.Add(new DotNetConfigSource());
+ => AddDotNetConfig(builder, null);
+
+ ///
+ /// Adds the DotNetConfig configuration provider to the .
+ ///
+ /// The to add dotnet config support to.
+ /// Optional path to use when building the configuration. See .
+ /// If not provided, the current directory will be used.
+ /// The .
+ ///
+ /// Simply invoke this method on a builder to add hierarchical dotnet-config support
+ /// to your app, for example:
+ ///
+ /// var config = new ConfigurationBuilder().AddDotNetConfig().Build();
+ ///
+ /// var ssl = config["http:sslVerify"];
+ ///
+ ///
+ public static IConfigurationBuilder AddDotNetConfig(this IConfigurationBuilder builder, string? path = null)
+ => builder.Add(new DotNetConfigSource(path));
}
}
diff --git a/src/Configuration/DotNetConfigProvider.cs b/src/Configuration/DotNetConfigProvider.cs
index d4cf22b..85f25c3 100644
--- a/src/Configuration/DotNetConfigProvider.cs
+++ b/src/Configuration/DotNetConfigProvider.cs
@@ -6,7 +6,9 @@ namespace DotNetConfig
{
class DotNetConfigProvider : ConfigurationProvider
{
- Config configuration = Config.Build();
+ Config configuration;
+
+ public DotNetConfigProvider(string? path = null) => configuration = Config.Build(path);
public override void Load()
{
@@ -25,7 +27,8 @@ public override void Load()
key += ConfigurationPath.KeyDelimiter + entry.Variable;
- data[key] = string.IsNullOrWhiteSpace(entry.RawValue) ? "true" : entry.RawValue!.Trim('"');
+ if (!data.ContainsKey(key))
+ data[key] = string.IsNullOrWhiteSpace(entry.RawValue) ? "true" : entry.RawValue!.Trim('"');
}
Data = data;
diff --git a/src/Configuration/DotNetConfigSource.cs b/src/Configuration/DotNetConfigSource.cs
index d5a9ba7..c9de4e5 100644
--- a/src/Configuration/DotNetConfigSource.cs
+++ b/src/Configuration/DotNetConfigSource.cs
@@ -4,6 +4,10 @@ namespace DotNetConfig
{
class DotNetConfigSource : IConfigurationSource
{
- public IConfigurationProvider Build(IConfigurationBuilder builder) => new DotNetConfigProvider();
+ readonly string? path;
+
+ public DotNetConfigSource(string? path = null) => this.path = path;
+
+ public IConfigurationProvider Build(IConfigurationBuilder builder) => new DotNetConfigProvider(path);
}
}