diff --git a/Fig.Core/Fig.Core.csproj b/Fig.Core/Fig.Core.csproj
index bada2eb..15bc26f 100644
--- a/Fig.Core/Fig.Core.csproj
+++ b/Fig.Core/Fig.Core.csproj
@@ -15,6 +15,7 @@
Robert Friberg et al
MIT
Fig
+ 8
diff --git a/Fig.Core/Settings.cs b/Fig.Core/Settings.cs
index d3479b7..bff1d2e 100644
--- a/Fig.Core/Settings.cs
+++ b/Fig.Core/Settings.cs
@@ -17,29 +17,21 @@ public sealed class Settings
///
private readonly IStringConverter _converter;
- ///
- /// 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
- ///
- 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;
}
@@ -76,10 +68,15 @@ public void Bind(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
@@ -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)
{
@@ -165,11 +162,8 @@ public bool TryGet(string key, out T result)
///
/// This is where the actual retrieval and type conversion happens
///
- 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);
diff --git a/Fig.Tests/BindToNullablePropertiesTests.cs b/Fig.Tests/BindToNullablePropertiesTests.cs
index d21bff5..8b652f0 100644
--- a/Fig.Tests/BindToNullablePropertiesTests.cs
+++ b/Fig.Tests/BindToNullablePropertiesTests.cs
@@ -1,5 +1,4 @@
using System;
-using System.Globalization;
using NUnit.Framework;
namespace Fig.Test;
diff --git a/Fig.Tests/BindingBehavior.cs b/Fig.Tests/BindingBehavior.cs
new file mode 100644
index 0000000..379f380
--- /dev/null
+++ b/Fig.Tests/BindingBehavior.cs
@@ -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(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();
+
+ 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;
+ }
+}
\ No newline at end of file