Skip to content

Commit

Permalink
feat: Added possibility to add rootkey for objects
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolaspierre1990 authored Jul 24, 2023
1 parent 9c45cd5 commit 9d8fc35
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 26 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.x'
dotnet-version: '6.x'
- name: Install dependencies
run: dotnet restore
- name: Build
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Copyright>Copyright 2020</Copyright>
<Version>1.0.6</Version>
<Version>2.0.0</Version>
<RepositoryType>git</RepositoryType>
<PackageIcon>icon.png</PackageIcon>
<PackageIconUrl />
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.8" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.8" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.*" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="7.*" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,54 @@ namespace Microsoft.Extensions.Configuration
public static class ObjectConfigurationExtensions
{
/// <summary>
/// Adds a <see cref="ObjectConfigurationProvider"/> to with a given configuration object.
/// Adds a <see cref="ObjectConfigurationProvider" /> to with a given configuration object.
/// </summary>
/// <param name="builder"><see cref="IConfigurationBuilder"/> to add provider to.</param>
/// <param name="builder"><see cref="IConfigurationBuilder" /> to add provider to.</param>
/// <param name="configurationObject">Configuration object with configuration values.</param>
/// <returns>Same <see cref="IConfigurationBuilder"/> instance to continue configuration.</returns>
/// <param name="rootKey">The root key.</param>
/// <returns>
/// Same <see cref="IConfigurationBuilder" /> instance to continue configuration.
/// </returns>
/// <exception cref="System.ArgumentNullException">
/// builder
/// or
/// configurationObject
/// </exception>
public static IConfigurationBuilder AddObject(this IConfigurationBuilder builder, object configurationObject, string rootKey)
{
if (builder is null)
{
throw new ArgumentNullException(nameof(builder));
}

if (configurationObject is null)
{
throw new ArgumentNullException(nameof(configurationObject));
}

if (rootKey is null)
{
throw new ArgumentNullException(nameof(rootKey));
}

return builder.Add((ObjectConfigurationSource source) =>
{
source.ConfigurationObject = configurationObject;
source.ConfigurationKey = rootKey;
});
}

/// <summary>
/// Adds a <see cref="ObjectConfigurationProvider" /> to with a given configuration object.
/// </summary>
/// <param name="builder"><see cref="IConfigurationBuilder" /> to add provider to.</param>
/// <param name="configurationObject">Configuration object with configuration values.</param>
/// <returns>
/// Same <see cref="IConfigurationBuilder" /> instance to continue configuration.
/// </returns>
/// <exception cref="System.ArgumentNullException">builder
/// or
/// configurationObject</exception>
public static IConfigurationBuilder AddObject(this IConfigurationBuilder builder, object configurationObject)
{
if (builder is null)
Expand Down
27 changes: 20 additions & 7 deletions src/Extensions.Configuration.Object/ObjectConfigurationProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,33 @@ public class ObjectConfigurationProvider : ConfigurationProvider
public object ConfigurationObject { get; set; }

/// <summary>
/// Creates an instance of <see cref="ObjectConfigurationProvider"/> using the provided configuration object.
/// Gets or sets the configuration root key.
/// </summary>
/// <value>
/// The configuration root key.
/// </value>
public string ConfigurationRootKey { get; set; }

/// <summary>
/// Creates an instance of <see cref="ObjectConfigurationProvider" /> using the provided configuration object.
/// </summary>
/// <param name="configurationObject">Object used as a source for configuration.</param>
public ObjectConfigurationProvider(object configurationObject)
{
ConfigurationObject = configurationObject ?? throw new ArgumentNullException(nameof(configurationObject));
}
/// <param name="configurationRootKey">The configuration root key.</param>
/// <exception cref="System.ArgumentNullException">configurationObject</exception>
public ObjectConfigurationProvider(object configurationObject, string configurationRootKey) : this(configurationObject) => ConfigurationRootKey = configurationRootKey;

/// <summary>
/// Initializes a new instance of the <see cref="ObjectConfigurationProvider"/> class.
/// </summary>
/// <param name="configurationObject">The configuration object.</param>
public ObjectConfigurationProvider(object configurationObject) => ConfigurationObject = configurationObject ?? throw new ArgumentNullException(nameof(configurationObject));

/// <summary>
/// Recursively loads values from <see cref="ConfigurationObject"/> to this provider.
/// </summary>
public override void Load()
{
LoadRecursively(null, ConfigurationObject);
LoadRecursively(ConfigurationRootKey, ConfigurationObject);
}

private void LoadRecursively(string currentKey, object section)
Expand All @@ -40,7 +53,7 @@ private void LoadRecursively(string currentKey, object section)
}

bool simpleValue = section is string || section.GetType().IsPrimitive
|| section is Uri || section is Guid;
|| section is Uri || section is Guid || section is TimeSpan;
if (simpleValue)
{
base.Set(currentKey, section.ToString());
Expand Down
12 changes: 11 additions & 1 deletion src/Extensions.Configuration.Object/ObjectConfigurationSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ public class ObjectConfigurationSource : IConfigurationSource
/// Object used as a source for configuration.
/// </summary>
public object ConfigurationObject { get; set; }
/// <summary>
/// Gets or sets the configuration key.
/// </summary>
/// <value>
/// The configuration key.
/// </value>
public string ConfigurationKey { get; set; }

/// <summary>
/// Builds the <see cref="ObjectConfigurationProvider"/> for this source.
Expand All @@ -25,7 +32,10 @@ public IConfigurationProvider Build(IConfigurationBuilder builder)
throw new ArgumentNullException($"Property {ConfigurationObject} needs to be set before calling method {nameof(Build)}.");
}

return new ObjectConfigurationProvider(ConfigurationObject);
return string.IsNullOrEmpty(ConfigurationKey)
? new ObjectConfigurationProvider(ConfigurationObject)
: new ObjectConfigurationProvider(ConfigurationObject, ConfigurationKey);

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,41 @@ public void AddObject_WithClassObject_ShouldLoadFieldsIntoConfiguration()
configuration["Logging:LogLevel:Microsoft"].Should().Be("Warning");
configuration["AllowedHosts"].Should().Be("*");
}

[Fact]
public void AddObject_WithClassObject_AndRootKey_ShouldLoadFieldsIntoConfiguration()
{
string rootKey = "MyRootKey";

var configuration = new ConfigurationBuilder()
.AddObject(new MyConfiguration
{
Position = new PositionConfiguration
{
Title = "Editor",
Name = "Joe Smith",
Age = 33
},
MyKey = "My appsettings.json Value",
Logging = new LoggingConfiguration
{
LogLevel = new LogLevelConfiguration
{
Default = "Information",
Microsoft = "Warning"
}
},
AllowedHosts = "*"
}, rootKey)
.Build();

configuration["MyRootKey:Position:Title"].Should().Be("Editor");
configuration["MyRootKey:Position:Name"].Should().Be("Joe Smith");
configuration["MyRootKey:Position:Age"].Should().Be("33");
configuration["MyRootKey:MyKey"].Should().Be("My appsettings.json Value");
configuration["MyRootKey:Logging:LogLevel:Default"].Should().Be("Information");
configuration["MyRootKey:Logging:LogLevel:Microsoft"].Should().Be("Warning");
configuration["MyRootKey:AllowedHosts"].Should().Be("*");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void AddObject_WithNull_ShouldThrow()
[Fact]
public void AddObject_OnNullConfigurationBuilder_ShouldThrow()
{
ConfigurationBuilder sut = null;
ConfigurationBuilder sut = default;

sut.Invoking(x => x.AddObject(default))
.Should().ThrowExactly<ArgumentNullException>();
Expand Down
21 changes: 11 additions & 10 deletions test/Extensionsions.Configuration.Object.UnitTests/UnitTests.csproj
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<IsPackable>false</IsPackable>
<AssemblyName>Extensions.Configuration.Object.UnitTests</AssemblyName>
<RootNamespace>Extensions.Configuration.Object.UnitTests</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoFixture.Xunit2" Version="4.14.0" />
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.9" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.9" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="3.1.9" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PackageReference Include="AutoFixture.Xunit2" Version="4.*" />
<PackageReference Include="FluentAssertions" Version="5.*" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.*" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.*" />
<PackageReference Include="xunit" Version="2.*">
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="xunit.runner.visualstudio" Version="2.*">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="1.3.0">
<PackageReference Include="coverlet.collector" Version="6.*">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down

0 comments on commit 9d8fc35

Please sign in to comment.