From 1ba6bfbac53c36c79655af2f8d172ab1432b8b73 Mon Sep 17 00:00:00 2001 From: Eric Rizzo Date: Wed, 16 Dec 2020 23:01:02 -0500 Subject: [PATCH 1/2] Added option to throw an exception for unresolved variables. --- .../ConfigurationTests.cs | 34 +++++++++++++++++++ .../ConfigurationSubstitution.csproj | 2 +- .../ConfigurationSubstitutor.cs | 15 ++++++-- .../IConfigurationBuilderExtensions.cs | 10 +++--- .../UndefinedConfigVariableException.cs | 12 +++++++ 5 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 ConfigurationSubstitutor/UndefinedConfigVariableException.cs diff --git a/ConfigurationSubstitution.Tests/ConfigurationTests.cs b/ConfigurationSubstitution.Tests/ConfigurationTests.cs index ac4ef83..3452685 100644 --- a/ConfigurationSubstitution.Tests/ConfigurationTests.cs +++ b/ConfigurationSubstitution.Tests/ConfigurationTests.cs @@ -121,5 +121,39 @@ public void Should_get_non_substituted_value_as_is() substituted.Should().Be("Boyz n the hood"); } + + [Fact] + public void Should_throw_for_non_resolved_variable() + { + var configurationBuilder = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "TestKey", "Test value {Foobar}" } + }) + .EnableSubstitutions(exceptionOnMissingVariables: true); + + var configuration = configurationBuilder.Build(); + + // Act + Action act = () => _ = configuration["TestKey"]; + + act.Should().Throw().WithMessage("*variable*{Foobar}*"); + } + + [Fact] + public void Should_ignore_non_resolved_variable() + { + var configurationBuilder = new ConfigurationBuilder() + .AddInMemoryCollection(new Dictionary + { + { "TestKey", "Test value {Foobar}" } + }) + .EnableSubstitutions(); + + var configuration = configurationBuilder.Build(); + + var value = configuration["TestKey"]; + value.Should().Be("Test value "); + } } } diff --git a/ConfigurationSubstitutor/ConfigurationSubstitution.csproj b/ConfigurationSubstitutor/ConfigurationSubstitution.csproj index 4d3adcc..3cfd026 100644 --- a/ConfigurationSubstitutor/ConfigurationSubstitution.csproj +++ b/ConfigurationSubstitutor/ConfigurationSubstitution.csproj @@ -18,7 +18,7 @@ GitHub https://github.com/molinch/ConfigurationSubstitutor netcore options configuration substitute substitution substituted variable aspnet - 1.0.2 + 1.1.0 diff --git a/ConfigurationSubstitutor/ConfigurationSubstitutor.cs b/ConfigurationSubstitutor/ConfigurationSubstitutor.cs index 7befdda..def23ce 100644 --- a/ConfigurationSubstitutor/ConfigurationSubstitutor.cs +++ b/ConfigurationSubstitutor/ConfigurationSubstitutor.cs @@ -9,16 +9,18 @@ public class ConfigurationSubstitutor private readonly string _startsWith; private readonly string _endsWith; private Regex _findSubstitutions; + private readonly bool _exceptionOnMissingVariables; - public ConfigurationSubstitutor() : this("{", "}") + public ConfigurationSubstitutor(bool exceptionOnMissingVariables = false) : this("{", "}", exceptionOnMissingVariables) { } - public ConfigurationSubstitutor(string substitutableStartsWith, string substitutableEndsWith) + public ConfigurationSubstitutor(string substitutableStartsWith, string substitutableEndsWith, bool exceptionOnMissingVariables = false) { _startsWith = substitutableStartsWith; _endsWith = substitutableEndsWith; _findSubstitutions = new Regex(@"(?<=" + Regex.Escape(_startsWith) + @")[^}{]*(?="+ Regex.Escape(_endsWith) + @")", RegexOptions.Compiled); + _exceptionOnMissingVariables = exceptionOnMissingVariables; } public string GetSubstituted(IConfiguration configuration, string key) @@ -34,7 +36,14 @@ public string ApplySubstitution(IConfiguration configuration, string value) var captures = _findSubstitutions.Matches(value).Cast().SelectMany(m => m.Captures.Cast()); foreach (var capture in captures) { - value = value.Replace(_startsWith + capture.Value + _endsWith, configuration[capture.Value]); + var substitutedValue = configuration[capture.Value]; + + if (substitutedValue == null && _exceptionOnMissingVariables) + { + throw new UndefinedConfigVariableException($"{_startsWith}{capture.Value}{_endsWith}"); + } + + value = value.Replace(_startsWith + capture.Value + _endsWith, substitutedValue); } return value; } diff --git a/ConfigurationSubstitutor/IConfigurationBuilderExtensions.cs b/ConfigurationSubstitutor/IConfigurationBuilderExtensions.cs index c77f5ef..028dc93 100644 --- a/ConfigurationSubstitutor/IConfigurationBuilderExtensions.cs +++ b/ConfigurationSubstitutor/IConfigurationBuilderExtensions.cs @@ -2,16 +2,18 @@ namespace ConfigurationSubstitution { + using System; + public static class IConfigurationBuilderExtensions { - public static IConfigurationBuilder EnableSubstitutions(this IConfigurationBuilder builder) + public static IConfigurationBuilder EnableSubstitutions(this IConfigurationBuilder builder, bool exceptionOnMissingVariables = false) { - return EnableSubstitutions(builder, new ConfigurationSubstitutor()); + return EnableSubstitutions(builder, new ConfigurationSubstitutor(exceptionOnMissingVariables)); } - public static IConfigurationBuilder EnableSubstitutions(this IConfigurationBuilder builder, string substitutableStartsWith, string substitutableEndsWith) + public static IConfigurationBuilder EnableSubstitutions(this IConfigurationBuilder builder, string substitutableStartsWith, string substitutableEndsWith, bool exceptionOnMissingVariables = false) { - return EnableSubstitutions(builder, new ConfigurationSubstitutor(substitutableStartsWith, substitutableEndsWith)); + return EnableSubstitutions(builder, new ConfigurationSubstitutor(substitutableStartsWith, substitutableEndsWith, exceptionOnMissingVariables)); } private static IConfigurationBuilder EnableSubstitutions(this IConfigurationBuilder builder, ConfigurationSubstitutor substitutor) diff --git a/ConfigurationSubstitutor/UndefinedConfigVariableException.cs b/ConfigurationSubstitutor/UndefinedConfigVariableException.cs new file mode 100644 index 0000000..39acd9f --- /dev/null +++ b/ConfigurationSubstitutor/UndefinedConfigVariableException.cs @@ -0,0 +1,12 @@ +namespace ConfigurationSubstitution +{ + using System; + + public class UndefinedConfigVariableException : Exception + { + public UndefinedConfigVariableException(string variableName) + : base($"No value found for configuration variable {variableName}") + { + } + } +} \ No newline at end of file From 3235fbb8f939423778780ce464523409ed3f14ef Mon Sep 17 00:00:00 2001 From: Eric Rizzo Date: Thu, 17 Dec 2020 13:19:44 -0500 Subject: [PATCH 2/2] Changed default to be throw when a variable can't be resolved. --- ConfigurationSubstitution.Tests/ConfigurationTests.cs | 4 ++-- ConfigurationSubstitutor/ConfigurationSubstitutor.cs | 4 ++-- ConfigurationSubstitutor/IConfigurationBuilderExtensions.cs | 6 ++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/ConfigurationSubstitution.Tests/ConfigurationTests.cs b/ConfigurationSubstitution.Tests/ConfigurationTests.cs index 3452685..ee1b76c 100644 --- a/ConfigurationSubstitution.Tests/ConfigurationTests.cs +++ b/ConfigurationSubstitution.Tests/ConfigurationTests.cs @@ -130,7 +130,7 @@ public void Should_throw_for_non_resolved_variable() { { "TestKey", "Test value {Foobar}" } }) - .EnableSubstitutions(exceptionOnMissingVariables: true); + .EnableSubstitutions(); var configuration = configurationBuilder.Build(); @@ -148,7 +148,7 @@ public void Should_ignore_non_resolved_variable() { { "TestKey", "Test value {Foobar}" } }) - .EnableSubstitutions(); + .EnableSubstitutions(exceptionOnMissingVariables: false); var configuration = configurationBuilder.Build(); diff --git a/ConfigurationSubstitutor/ConfigurationSubstitutor.cs b/ConfigurationSubstitutor/ConfigurationSubstitutor.cs index def23ce..baa7db3 100644 --- a/ConfigurationSubstitutor/ConfigurationSubstitutor.cs +++ b/ConfigurationSubstitutor/ConfigurationSubstitutor.cs @@ -11,11 +11,11 @@ public class ConfigurationSubstitutor private Regex _findSubstitutions; private readonly bool _exceptionOnMissingVariables; - public ConfigurationSubstitutor(bool exceptionOnMissingVariables = false) : this("{", "}", exceptionOnMissingVariables) + public ConfigurationSubstitutor(bool exceptionOnMissingVariables = true) : this("{", "}", exceptionOnMissingVariables) { } - public ConfigurationSubstitutor(string substitutableStartsWith, string substitutableEndsWith, bool exceptionOnMissingVariables = false) + public ConfigurationSubstitutor(string substitutableStartsWith, string substitutableEndsWith, bool exceptionOnMissingVariables = true) { _startsWith = substitutableStartsWith; _endsWith = substitutableEndsWith; diff --git a/ConfigurationSubstitutor/IConfigurationBuilderExtensions.cs b/ConfigurationSubstitutor/IConfigurationBuilderExtensions.cs index 028dc93..6c37c55 100644 --- a/ConfigurationSubstitutor/IConfigurationBuilderExtensions.cs +++ b/ConfigurationSubstitutor/IConfigurationBuilderExtensions.cs @@ -2,16 +2,14 @@ namespace ConfigurationSubstitution { - using System; - public static class IConfigurationBuilderExtensions { - public static IConfigurationBuilder EnableSubstitutions(this IConfigurationBuilder builder, bool exceptionOnMissingVariables = false) + public static IConfigurationBuilder EnableSubstitutions(this IConfigurationBuilder builder, bool exceptionOnMissingVariables = true) { return EnableSubstitutions(builder, new ConfigurationSubstitutor(exceptionOnMissingVariables)); } - public static IConfigurationBuilder EnableSubstitutions(this IConfigurationBuilder builder, string substitutableStartsWith, string substitutableEndsWith, bool exceptionOnMissingVariables = false) + public static IConfigurationBuilder EnableSubstitutions(this IConfigurationBuilder builder, string substitutableStartsWith, string substitutableEndsWith, bool exceptionOnMissingVariables = true) { return EnableSubstitutions(builder, new ConfigurationSubstitutor(substitutableStartsWith, substitutableEndsWith, exceptionOnMissingVariables)); }