ConfigurationBindingExtensions
.Bind(instance, type, memberInfo, key, delimiter) creates a binding that reads source 'instance' object tree as IConfiguration compatible key-values pairs. This is inverse binding to what Microsoft's ConfigurationBinder provides.
// Create object tree
var map = new Dictionary<string, object>
{
{ "AudioSettings", new AudioSettings() },
{ "UISettings", new UISettings() },
{ "UserSettings", new UserSettings() },
};
// Create binding to 'map' (takes reference into closure)
IEnumerable<BindInfo> mapBinding = ConfigurationBindingExtensions.Bind(map, map.GetType());
IEnumerable<KeyValuePair<string, string?>> mapBindingAsKeyValues = mapBinding.Select<BindInfo, KeyValuePair<string, string?>>(line => line);
// Read a snapshot of 'map' as key-values
List<KeyValuePair<string, string?>> keyValues = mapBinding.Select<BindInfo, KeyValuePair<string, string?>>(line => line).ToList();
// Print snapshot
foreach (var kv in keyValues) Console.WriteLine(kv);
// [AudioSettings: SoundVolume, 50]
// [AudioSettings: MusicVolume, 25]
// [AudioSettings: MusicTempo, TempoLow, TempoMedium]
// [UISettings: GfxQuality, 20]
// [UISettings: AnimationSpeed, 50]
// [UserSettings: PlayerName, <name here>]
// [UserSettings: Email,]
public record AudioSettings
{
public float SoundVolume { get; set; } = 50f;
public float MusicVolume { get; set; } = 25f;
public MusicTempo MusicTempo { get; set; } = MusicTempo.TempoLow | MusicTempo.TempoMedium;
}
[Flags]
public enum MusicTempo : int
{
TempoLow = 1,
TempoMedium = 2,
TempoHigh = 4,
}
public record UISettings
{
public float GfxQuality { get; set; } = 20f;
public float AnimationSpeed { get; set; } = 50f;
}
public record UserSettings
{
public string PlayerName { get; set; } = "<name here>";
public string? Email { get; set; }
public List<string> Tags { get; set; } = new();
}
Binding can be enumerated again to reflect current contents of source object as key-values.
// Modify source 'map'
((AudioSettings)map["AudioSettings"]).MusicVolume = 100;
((AudioSettings)map["AudioSettings"]).SoundVolume = 100;
((UserSettings)map["UserSettings"]).Email = "user@email";
// Read new snapshot of 'map' as key-values
foreach (var kv in mapBindingAsKeyValues) Console.WriteLine(kv);
// [AudioSettings: SoundVolume, 100]
// [AudioSettings: MusicVolume, 100]
// [AudioSettings: MusicTempo, TempoLow, TempoMedium]
// [UISettings: GfxQuality, 20]
// [UISettings: AnimationSpeed, 50]
// [UserSettings: PlayerName, <name here>]
// [UserSettings: Email, user@email]
.Bind(null, type) scans key tree structure for information available in 'type' when null is passed as 'instance' argument.
IEnumerable<BindInfo> typeLevelBinding = ConfigurationBindingExtensions.Bind(instance: null, type: typeof(AudioSettings));
foreach (var kv in typeLevelBinding) Console.WriteLine(kv);
// BindInfo { Key = SoundVolume, Value = , Instance = , Type = System.Single, MemberInfo = Single SoundVolume, Annotations = System.Object[] }
// BindInfo { Key = MusicVolume, Value = , Instance = , Type = System.Single, MemberInfo = Single MusicVolume, Annotations = System.Object[] }
// BindInfo { Key = MusicTempo, Value = , Instance = , Type = MusicTempo, MemberInfo = MusicTempo MusicTempo, Annotations = System.Object[] }
Full Example
Full example
using Avalanche.Configuration;
using static Avalanche.Configuration.ConfigurationBindingExtensions;
public class configurationbindingextensions
{
public static void Run()
{
{
// <01>
// Create object tree
var map = new Dictionary<string, object>
{
{ "AudioSettings", new AudioSettings() },
{ "UISettings", new UISettings() },
{ "UserSettings", new UserSettings() },
};
// Create binding to 'map' (takes reference into closure)
IEnumerable<BindInfo> mapBinding = ConfigurationBindingExtensions.Bind(map, map.GetType());
IEnumerable<KeyValuePair<string, string?>> mapBindingAsKeyValues = mapBinding.Select<BindInfo, KeyValuePair<string, string?>>(line => line);
// Read a snapshot of 'map' as key-values
List<KeyValuePair<string, string?>> keyValues = mapBinding.Select<BindInfo, KeyValuePair<string, string?>>(line => line).ToList();
// Print snapshot
foreach (var kv in keyValues) Console.WriteLine(kv);
// [AudioSettings: SoundVolume, 50]
// [AudioSettings: MusicVolume, 25]
// [AudioSettings: MusicTempo, TempoLow, TempoMedium]
// [UISettings: GfxQuality, 20]
// [UISettings: AnimationSpeed, 50]
// [UserSettings: PlayerName, <name here>]
// [UserSettings: Email,]
// </01>
// <02>
// Modify source 'map'
((AudioSettings)map["AudioSettings"]).MusicVolume = 100;
((AudioSettings)map["AudioSettings"]).SoundVolume = 100;
((UserSettings)map["UserSettings"]).Email = "user@email";
// Read new snapshot of 'map' as key-values
foreach (var kv in mapBindingAsKeyValues) Console.WriteLine(kv);
// [AudioSettings: SoundVolume, 100]
// [AudioSettings: MusicVolume, 100]
// [AudioSettings: MusicTempo, TempoLow, TempoMedium]
// [UISettings: GfxQuality, 20]
// [UISettings: AnimationSpeed, 50]
// [UserSettings: PlayerName, <name here>]
// [UserSettings: Email, user@email]
// </02>
}
{
// <04>
IEnumerable<BindInfo> typeLevelBinding = ConfigurationBindingExtensions.Bind(instance: null, type: typeof(AudioSettings));
foreach (var kv in typeLevelBinding) Console.WriteLine(kv);
// BindInfo { Key = SoundVolume, Value = , Instance = , Type = System.Single, MemberInfo = Single SoundVolume, Annotations = System.Object[] }
// BindInfo { Key = MusicVolume, Value = , Instance = , Type = System.Single, MemberInfo = Single MusicVolume, Annotations = System.Object[] }
// BindInfo { Key = MusicTempo, Value = , Instance = , Type = MusicTempo, MemberInfo = MusicTempo MusicTempo, Annotations = System.Object[] }
// </04>
}
}
}
// <03>
public record AudioSettings
{
public float SoundVolume { get; set; } = 50f;
public float MusicVolume { get; set; } = 25f;
public MusicTempo MusicTempo { get; set; } = MusicTempo.TempoLow | MusicTempo.TempoMedium;
}
[Flags]
public enum MusicTempo : int
{
TempoLow = 1,
TempoMedium = 2,
TempoHigh = 4,
}
public record UISettings
{
public float GfxQuality { get; set; } = 20f;
public float AnimationSpeed { get; set; } = 50f;
}
public record UserSettings
{
public string PlayerName { get; set; } = "<name here>";
public string? Email { get; set; }
public List<string> Tags { get; set; } = new();
}
// </03>