diff --git a/ConfigurationSubstitution.Tests/ConfigurationTests.cs b/ConfigurationSubstitution.Tests/ConfigurationTests.cs index ac4ef83..ee1b76c 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(); + + 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(exceptionOnMissingVariables: false); + + 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..baa7db3 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 = true) : this("{", "}", exceptionOnMissingVariables) { } - public ConfigurationSubstitutor(string substitutableStartsWith, string substitutableEndsWith) + public ConfigurationSubstitutor(string substitutableStartsWith, string substitutableEndsWith, bool exceptionOnMissingVariables = true) { _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..6c37c55 100644 --- a/ConfigurationSubstitutor/IConfigurationBuilderExtensions.cs +++ b/ConfigurationSubstitutor/IConfigurationBuilderExtensions.cs @@ -4,14 +4,14 @@ namespace ConfigurationSubstitution { public static class IConfigurationBuilderExtensions { - public static IConfigurationBuilder EnableSubstitutions(this IConfigurationBuilder builder) + public static IConfigurationBuilder EnableSubstitutions(this IConfigurationBuilder builder, bool exceptionOnMissingVariables = true) { - 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 = true) { - 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