Skip to content

Commit

Permalink
fixes #45 and #46
Browse files Browse the repository at this point in the history
  • Loading branch information
rofr committed Dec 8, 2023
1 parent 075098d commit ababe84
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 22 deletions.
1 change: 1 addition & 0 deletions Fig.Core/Fig.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<Copyright>Robert Friberg et al</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RootNamespace>Fig</RootNamespace>
<LangVersion>8</LangVersion>
</PropertyGroup>
<ItemGroup>
<None Remove="appsettings.json" />
Expand Down
36 changes: 15 additions & 21 deletions Fig.Core/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,21 @@ public sealed class Settings
/// </summary>
private readonly IStringConverter _converter;

/// <summary>
/// Path to the node in the tree to bind to for example:
/// Given keys A.B.C and A.B.D, a binding path of A.B
/// will bind the values of A.B.C and A.B.D to properties C and D of this type
/// </summary>
private readonly string _bindingPath;

public override String ToString()
{
if (SettingsDictionary is null) return base.ToString();
return SettingsDictionary.AsString();
}

private Settings(string bindingPath = null, IStringConverter converter = null)
private Settings(IStringConverter converter = null)
{
_converter = converter ?? new InvariantStringConverter();
_bindingPath = bindingPath ?? "";
}


internal Settings(LayeredSettingsDictionary settingsDictionary,
string bindingPath = null, IStringConverter converter = null)
: this(bindingPath, converter)
IStringConverter converter = null)
: this(converter)
{
SettingsDictionary = settingsDictionary;
}
Expand Down Expand Up @@ -76,10 +68,15 @@ public void Bind<T>(T target, bool validate = true, string path = null)
BindProperties(target, validate, path);
}

internal string Combine(string bindingPath, string typeName, string propertyName)
{
if (bindingPath is null) return $"{typeName}.{propertyName}";
if (bindingPath.Trim() == "") return propertyName;
else return $"{bindingPath}.{propertyName}";
}

private void BindProperties(object target, bool validate, string bindingPath = null)
{
bindingPath = bindingPath ?? _bindingPath;

{
foreach (var property in target.GetType().GetProperties())
{
try
Expand All @@ -89,12 +86,12 @@ private void BindProperties(object target, bool validate, string bindingPath = n
if (propertyIsReadonly
|| property.PropertyType.IsAbstract
|| property.PropertyType.IsInterface) continue;
var name = String.IsNullOrEmpty(bindingPath?.Trim()) ? property.Name : $"{bindingPath}.{property.Name}";

var name = Combine(bindingPath, property.PropertyType.Name, property.Name);
var defaultValue = property.GetValue(target);
var required = validate && defaultValue is null;
var result = GetPropertyValue(property, name, required);
property.SetValue(target, result);
if (result != null) property.SetValue(target, result);
}
catch (TargetInvocationException ex)
{
Expand Down Expand Up @@ -165,11 +162,8 @@ public bool TryGet<T>(string key, out T result)
/// <summary>
/// This is where the actual retrieval and type conversion happens
/// </summary>
private object Get(Type propertyType, string propertyName)
private object Get(Type propertyType, string key)
{
var key = propertyName;
if (_bindingPath.Length > 0) key = _bindingPath + "." + key;

if (!SettingsDictionary.TryGetValue(key, out string value))
{
throw new KeyNotFoundException(key);
Expand Down
1 change: 0 additions & 1 deletion Fig.Tests/BindToNullablePropertiesTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Globalization;
using NUnit.Framework;

namespace Fig.Test;
Expand Down
44 changes: 44 additions & 0 deletions Fig.Tests/BindingBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using NUnit.Framework;

namespace Fig.Test;

public class BindingBehavior
{
[Test]
public void EmptyPathBindsToRoot()
{
var settings = new SettingsBuilder()
.UseSettingsDictionary(new SettingsDictionary()
{
{"Hello", "Hi"},
{"Number", "16"},
{"OtherNumber", "16"}
}).Build();

var settingsWithDefaults = settings.Bind<SettingsWithDefaults>(path:"");
Assert.AreEqual(settingsWithDefaults.Hello, "Hi");
Assert.AreEqual(settingsWithDefaults.Number, 16);
Assert.AreEqual(settingsWithDefaults.OtherNumber, 16);

}

[Test]
public void CanBindToNullableProperties()
{
//empty dictionary
var settings = new SettingsBuilder().Build();
var settingsWithDefaults = settings.Bind<SettingsWithDefaults>();

Assert.AreEqual(settingsWithDefaults.Hello, "Hello");
Assert.AreEqual(settingsWithDefaults.Number, 42);
Assert.AreEqual(settingsWithDefaults.OtherNumber, 42);
}

private class SettingsWithDefaults
{
public int Number { get; set; } = 42;
public string Hello { get; set; } = nameof(Hello);

public int? OtherNumber { get; set; } = 42;
}
}

0 comments on commit ababe84

Please sign in to comment.