-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added Morestachio Config Transformator
- Loading branch information
Showing
14 changed files
with
641 additions
and
6 deletions.
There are no files selected for viewing
18 changes: 18 additions & 0 deletions
18
Morestachio.Configuration.Transform.Tests/Morestachio.Configuration.Transform.Tests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFrameworks>netstandard2.0;net461;</TargetFrameworks> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" /> | ||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="5.0.0" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" /> | ||
<PackageReference Include="NUnit" Version="3.13.1" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Morestachio.Configuration.Transform\Morestachio.Configuration.Transform.csproj" /> | ||
</ItemGroup> | ||
|
||
</Project> |
110 changes: 110 additions & 0 deletions
110
Morestachio.Configuration.Transform.Tests/TestConfigTransformation.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Text; | ||
using Microsoft.Extensions.Configuration; | ||
using NUnit.Framework; | ||
|
||
namespace Morestachio.Configuration.Transform.Tests | ||
{ | ||
[TestFixture(true)] | ||
[TestFixture(false)] | ||
public class TestConfigTransformation | ||
{ | ||
private readonly bool _useBuildTime; | ||
|
||
public TestConfigTransformation(bool useBuildTime) | ||
{ | ||
_useBuildTime = useBuildTime; | ||
} | ||
|
||
public IMorestachioConfigurationBuilder CreateConfig(Func<IConfigurationBuilder, IConfigurationBuilder> builderConfig = null) | ||
{ | ||
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); | ||
configurationBuilder = builderConfig != null ? builderConfig(configurationBuilder) : configurationBuilder; | ||
if (_useBuildTime) | ||
{ | ||
return configurationBuilder.UseBuildtimeMorestachio(); | ||
} | ||
else | ||
{ | ||
return configurationBuilder.UseRuntimeMorestachio(); | ||
} | ||
} | ||
|
||
[Test] | ||
public void TestCanReplaceBuildTime() | ||
{ | ||
var builder = CreateConfig(c => c | ||
.AddInMemoryCollection(new[] | ||
{ | ||
new KeyValuePair<string, string>("Str", "test"), | ||
new KeyValuePair<string, string>("Number", "mex{{2 + 2}}") | ||
})); | ||
|
||
var config = builder.Build(); | ||
Assert.That(config["Str"], Is.EqualTo("test")); | ||
Assert.That(config["Number"], Is.EqualTo("4")); | ||
} | ||
|
||
[Test] | ||
public void TestCanReplaceBuildTimeWithDeepPaths() | ||
{ | ||
var builder = CreateConfig(c => c.AddJsonStream(JsonfyText( | ||
@"{ | ||
""strValue"": ""test"", | ||
""objValue"": { | ||
""constValue"": 123, | ||
""valueA"": ""mex{{1 + 2 + 3}}"" | ||
}, | ||
""valueB"": ""mex{{5 * 3}}"" | ||
}"))); | ||
|
||
var config = builder.Build(); | ||
Assert.That(config["strValue"], Is.EqualTo("test")); | ||
Assert.That(config["objValue:constValue"], Is.EqualTo("123")); | ||
Assert.That(config["objValue:valueA"], Is.EqualTo("6")); | ||
Assert.That(config["valueB"], Is.EqualTo("15")); | ||
} | ||
|
||
[Test] | ||
public void TestCanReplaceBuildTimeWithArguments() | ||
{ | ||
var builder = CreateConfig(c => c.AddJsonStream(JsonfyText( | ||
@"{ | ||
""strValue"": ""test"", | ||
""objValue"": { | ||
""constValue"": 123, | ||
""exp_mEx"": ""mex{{1 + 2 + 3 - Cores}}"", | ||
""expRoot_mEx"": ""mex{{1 + 2 + 3 - Cores}}"", | ||
}, | ||
""expA_mEx"": ""mex{{Cores * 3}}"" | ||
}"))) | ||
|
||
.UseValues(null, new Dictionary<string, object>() | ||
{ | ||
{ "Cores", 5 } | ||
}) | ||
.UseValues("objValue:exp_mEx", new Dictionary<string, object>() | ||
{ | ||
{ "Cores", 1 } | ||
}) | ||
.UseValues("objValue", new Dictionary<string, object>() | ||
{ | ||
{ "Cores", 3 } | ||
}); | ||
|
||
var config = builder.Build(); | ||
Assert.That(config["strValue"], Is.EqualTo("test")); | ||
Assert.That(config["objValue:constValue"], Is.EqualTo("123")); | ||
Assert.That(config["objValue:exp_mEx"], Is.EqualTo("5")); | ||
Assert.That(config["objValue:expRoot_mEx"], Is.EqualTo("3")); | ||
Assert.That(config["expA_mEx"], Is.EqualTo("15")); | ||
} | ||
|
||
private Stream JsonfyText(string text) | ||
{ | ||
return new MemoryStream(Encoding.UTF8.GetBytes(text)); | ||
} | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
Morestachio.Configuration.Transform/IMorestachioConfigurationBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using Microsoft.Extensions.Configuration; | ||
|
||
namespace Morestachio.Configuration.Transform | ||
{ | ||
/// <summary> | ||
/// A morestachio config builder | ||
/// </summary> | ||
public interface IMorestachioConfigurationBuilder : IConfigurationBuilder | ||
{ | ||
MorestachioConfigOptions Options { get; set; } | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
Morestachio.Configuration.Transform/Morestachio.Configuration.Transform.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFrameworks>netstandard2.0;net461;</TargetFrameworks> | ||
<PackageTags>Formatter, C#, Engine, NetStandard, Configuration</PackageTags> | ||
<Description>A adapter for using Morestachio with the IConfiguration system.</Description> | ||
<PackageReleaseNotes>Several Bugfixes and Formatter refactoring</PackageReleaseNotes> | ||
<BuildPackage>true</BuildPackage> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\Morestachio\Morestachio.csproj" /> | ||
</ItemGroup> | ||
<Import Project="../AfterDirectory.Build.props"></Import> | ||
|
||
</Project> |
60 changes: 60 additions & 0 deletions
60
Morestachio.Configuration.Transform/MorestachioBuildtimeConfigBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using System.Collections.Generic; | ||
using Microsoft.Extensions.Configuration; | ||
|
||
namespace Morestachio.Configuration.Transform | ||
{ | ||
/// <summary> | ||
/// Wraps the <see cref="IConfigurationBuilder"/> and preprocesses all keys that matches the <see cref="MorestachioConfigOptions.TransformCondition"/> | ||
/// </summary> | ||
public class MorestachioBuildtimeConfigBuilder : IMorestachioConfigurationBuilder | ||
{ | ||
private readonly IConfigurationBuilder _builder; | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
/// <param name="builder"></param> | ||
public MorestachioBuildtimeConfigBuilder(IConfigurationBuilder builder) | ||
{ | ||
_builder = builder; | ||
Options = new MorestachioConfigOptions(); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IConfigurationBuilder Add(IConfigurationSource source) | ||
{ | ||
return _builder.Add(source); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IConfigurationRoot Build() | ||
{ | ||
var configurationRoot = _builder.Build(); | ||
foreach (var keyValuePair in configurationRoot.AsEnumerable()) | ||
{ | ||
if (Options.TransformCondition(keyValuePair)) | ||
{ | ||
var transformValue = MorestachioConfig | ||
.TransformValue(new KeyValuePair<string, string>(keyValuePair.Key, keyValuePair.Value), Options); | ||
configurationRoot[transformValue.Key] = transformValue.Value; | ||
} | ||
} | ||
return configurationRoot; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IDictionary<string, object> Properties | ||
{ | ||
get { return _builder.Properties; } | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IList<IConfigurationSource> Sources | ||
{ | ||
get { return _builder.Sources; } | ||
} | ||
|
||
/// <inheritdoc /> | ||
public MorestachioConfigOptions Options { get; set; } | ||
} | ||
} |
114 changes: 114 additions & 0 deletions
114
Morestachio.Configuration.Transform/MorestachioConfig.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Primitives; | ||
using Morestachio.Framework.Expression.Parser; | ||
|
||
namespace Morestachio.Configuration.Transform | ||
{ | ||
/// <summary> | ||
/// Wrapper for Runtime Morestachio configs | ||
/// </summary> | ||
public class MorestachioConfig : IConfiguration | ||
{ | ||
protected IConfiguration Config { get; } | ||
protected MorestachioConfigOptions Options { get; } | ||
|
||
/// <summary> | ||
/// | ||
/// </summary> | ||
/// <param name="config"></param> | ||
/// <param name="options"></param> | ||
public MorestachioConfig(IConfiguration config, MorestachioConfigOptions options) | ||
{ | ||
Config = config; | ||
Options = options; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IConfigurationSection GetSection(string key) | ||
{ | ||
return new MorestachioConfigSection(Config.GetSection(key), Options); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IEnumerable<IConfigurationSection> GetChildren() | ||
{ | ||
return Config.GetChildren().Select(e => new MorestachioConfigSection(e, Options)); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IChangeToken GetReloadToken() | ||
{ | ||
return Config.GetReloadToken(); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public string this[string key] | ||
{ | ||
get | ||
{ | ||
return CheckAndTransformValue(key, Config[key], Options).Value; | ||
} | ||
set { Config[key] = value; } | ||
} | ||
|
||
/// <summary> | ||
/// Checks if a key matches the <see cref="MorestachioConfigOptions.TransformCondition"/> and converts it | ||
/// </summary> | ||
/// <returns></returns> | ||
public static KeyValuePair<string, string> CheckAndTransformValue(string key, string value, MorestachioConfigOptions options) | ||
{ | ||
if (options.TransformCondition(new KeyValuePair<string, string>(key, value))) | ||
{ | ||
return TransformValue(new KeyValuePair<string, string>(key, value), options); | ||
} | ||
|
||
return new KeyValuePair<string, string>(key, value); | ||
} | ||
|
||
/// <summary> | ||
/// Transforms the value by using <see cref="Options"/> | ||
/// </summary> | ||
/// <returns></returns> | ||
public static KeyValuePair<string, string> TransformValue(KeyValuePair<string, string> keyValue, MorestachioConfigOptions options) | ||
{ | ||
keyValue = options.PreTransform(keyValue); | ||
var parserOptions = options.ParserOptions(); | ||
var values = new Dictionary<string, object>(); | ||
if (options.Values.TryGetValue(string.Empty, out var rootValues)) | ||
{ | ||
foreach (var rootValue in rootValues) | ||
{ | ||
values[rootValue.Key] = rootValue.Value; | ||
} | ||
} | ||
|
||
IList<string> keyPaths = new List<string>(); | ||
foreach (var keyPathPart in keyValue.Key.Split(':')) | ||
{ | ||
keyPaths.Add(keyPathPart); | ||
var keyPath = string.Join(":", keyPaths); | ||
if (options.Values.TryGetValue(keyPath, out var specificValues)) | ||
{ | ||
foreach (var specificValue in specificValues) | ||
{ | ||
values[specificValue.Key] = specificValue.Value; | ||
} | ||
} | ||
} | ||
var valueTask = ExpressionParser.EvaluateExpression(keyValue.Value, parserOptions, values); | ||
string result; | ||
if (valueTask.IsCompleted) | ||
{ | ||
result = valueTask.Result?.ToString(); | ||
} | ||
else | ||
{ | ||
result = valueTask.GetAwaiter().GetResult()?.ToString(); | ||
} | ||
|
||
return options.PostTransform(new KeyValuePair<string, string>(keyValue.Key, result)); | ||
} | ||
} | ||
} |
Oops, something went wrong.