| | | 1 | | using System; |
| | | 2 | | using System.Collections.Generic; |
| | | 3 | | |
| | | 4 | | namespace AmbientServices; |
| | | 5 | | |
| | | 6 | | /// <summary> |
| | | 7 | | /// A settings set implementation that contains settings that are assigned at construction and cannot be changed. |
| | | 8 | | /// </summary> |
| | | 9 | | /// <remarks> |
| | | 10 | | /// <pitch>A frozen snapshot of settings fixed at construction — the cheapest possible reads and complete predictability |
| | | 11 | | /// <pledge><see cref="IAmbientSettingsSet"/></pledge> |
| | | 12 | | /// <pledge>Values never change after construction; the set reports itself immutable and any attempt to change a setting |
| | | 13 | | /// <plan>Plain (non-concurrent) dictionaries hold the raw and typed values, safe for unsynchronized concurrent reads pr |
| | | 14 | | /// </remarks> |
| | | 15 | | public class AmbientImmutableSettingsSet : IAmbientSettingsSet |
| | | 16 | | { |
| | | 17 | | /// <summary> |
| | | 18 | | /// The set name of the default settings set. |
| | | 19 | | /// </summary> |
| | | 20 | | public const string DefaultSetName = "Immutable"; |
| | | 21 | | private readonly Dictionary<string, string> _rawValues; |
| | | 22 | | private readonly Dictionary<string, object> _typedValues; |
| | | 23 | | |
| | | 24 | | /// <summary> |
| | | 25 | | /// Constructs the default ambient settings set. |
| | | 26 | | /// </summary> |
| | | 27 | | internal AmbientImmutableSettingsSet() |
| | 2 | 28 | | : this(DefaultSetName) |
| | | 29 | | { |
| | 2 | 30 | | } |
| | | 31 | | /// <summary> |
| | | 32 | | /// Constructs a new immutable ambient settings set with the specified values. |
| | | 33 | | /// </summary> |
| | | 34 | | /// <param name="name">The name of the set.</param> |
| | 2 | 35 | | public AmbientImmutableSettingsSet(string name) |
| | | 36 | | { |
| | 2 | 37 | | SetName = name; |
| | 2 | 38 | | _rawValues = new Dictionary<string, string>(); |
| | 2 | 39 | | _typedValues = new Dictionary<string, object>(); |
| | 2 | 40 | | } |
| | | 41 | | /// <summary> |
| | | 42 | | /// Constructs a new immutable ambient settings set with the specified values. |
| | | 43 | | /// </summary> |
| | | 44 | | /// <param name="name">The name of the set.</param> |
| | | 45 | | /// <param name="values">A set of name-value pairs to use for the initial values for the set.</param> |
| | 2 | 46 | | public AmbientImmutableSettingsSet(string name, IDictionary<string, string> values) |
| | | 47 | | { |
| | 2 | 48 | | SetName = name; |
| | 2 | 49 | | _rawValues = new Dictionary<string, string>(values); |
| | 2 | 50 | | _typedValues = new Dictionary<string, object>(); |
| | 2 | 51 | | if (values != null) |
| | | 52 | | { |
| | 2 | 53 | | foreach (string key in values.Keys) |
| | | 54 | | { |
| | 2 | 55 | | IAmbientSettingInfo? ps = SettingsRegistry.DefaultRegistry.TryGetSetting(key); |
| | 2 | 56 | | _typedValues[key] = (ps != null) ? ps.Convert(this, values[key]) : values[key]; |
| | | 57 | | } |
| | | 58 | | } |
| | 2 | 59 | | } |
| | | 60 | | |
| | | 61 | | /// <summary> |
| | | 62 | | /// Gets the name of the settings set so that a settings consumer can know where a changed setting value came from. |
| | | 63 | | /// </summary> |
| | | 64 | | public string SetName { get; } |
| | | 65 | | /// <summary> |
| | | 66 | | /// Gets the current raw (string) value for the specified key, or null if the setting is not set. |
| | | 67 | | /// </summary> |
| | | 68 | | /// <param name="key">A key identifying the setting whose value is to be retrieved.</param> |
| | | 69 | | /// <returns>The setting value, or null if the setting is not set.</returns> |
| | | 70 | | |
| | | 71 | | public string? GetRawValue(string key) |
| | | 72 | | { |
| | 2 | 73 | | return _rawValues.TryGetValue(key, out string? value) ? value : null; |
| | | 74 | | } |
| | | 75 | | /// <summary> |
| | | 76 | | /// Gets the current typed value for the setting with the specified key, or null if the setting is not set. |
| | | 77 | | /// </summary> |
| | | 78 | | /// <param name="key">A key identifying the setting whose value is to be retrieved.</param> |
| | | 79 | | /// <returns>The setting value, or null if the setting is not set.</returns> |
| | | 80 | | public object? GetTypedValue(string key) |
| | | 81 | | { |
| | 2 | 82 | | return _typedValues.TryGetValue(key, out object? value) ? value : null; |
| | | 83 | | } |
| | | 84 | | /// <summary> |
| | | 85 | | /// Gets whether or not the settings set is mutable. |
| | | 86 | | /// </summary> |
| | 2 | 87 | | public bool SettingsAreMutable => false; |
| | | 88 | | /// <summary> |
| | | 89 | | /// Changes the specified setting, if possible. |
| | | 90 | | /// For many ambient settings services, the value will only be reflected in memory until the process shuts down, but |
| | | 91 | | /// </summary> |
| | | 92 | | /// <param name="key">A string that uniquely identifies the setting.</param> |
| | | 93 | | /// <param name="value">The new string value for the setting, or null if the setting should be removed.</param> |
| | | 94 | | /// <returns>Whether or not the setting actually changed (it may have had already the same value).</returns> |
| | 2 | 95 | | public bool ChangeSetting(string key, string? value) => throw new InvalidOperationException($"{nameof(AmbientImmutab |
| | | 96 | | |
| | | 97 | | /// <summary> |
| | | 98 | | /// Gets a string representing the settings instance. |
| | | 99 | | /// </summary> |
| | | 100 | | /// <returns></returns> |
| | | 101 | | public override string ToString() |
| | | 102 | | { |
| | 2 | 103 | | return "ImmutableSettings: " + SetName; |
| | | 104 | | } |
| | | 105 | | } |