diff --git a/src/Hocon.Configuration/Config.cs b/src/Hocon.Configuration/Config.cs index 6e32b800..b2c0b91d 100644 --- a/src/Hocon.Configuration/Config.cs +++ b/src/Hocon.Configuration/Config.cs @@ -18,22 +18,32 @@ namespace Hocon /// public class Config : HoconRoot { + [Obsolete("For json serialization/deserialization only", true)] + private Config() + { + } + /// /// /// Initializes a new instance of the class. /// - private Config() + private Config(HoconValue value, Config fallback) { + Fallback = fallback; + Value = value; + + Root = GetRootValue(); } - /// + /// /// The root node to base this configuration. /// "The root value cannot be null." public Config(HoconRoot root) : base(root?.Value, root?.Substitutions ?? Enumerable.Empty()) { + Root = GetRootValue(); } - /// + /// /// The configuration to use as the primary source. /// The configuration to use as a secondary source. /// The source configuration cannot be null. @@ -41,6 +51,8 @@ public Config(HoconRoot source, Config fallback) : base(source?.Value, source?.Substitutions ?? Enumerable.Empty()) { Fallback = fallback; + + Root = GetRootValue(); } /// @@ -54,27 +66,12 @@ public Config(HoconRoot source, Config fallback) : base(source?.Value, /// /// The configuration used as a secondary source. /// - public Config Fallback { get; private set; } + public Config Fallback { get; } /// /// The root node of this configuration section /// - public virtual HoconValue Root - { - get - { - var elements = new List(); - for (var config = this; config != null; config = config.Fallback?.Copy()) - { - elements.AddRange(config.Value); - } - - var aggregated = new HoconValue(null); - aggregated.AddRange(elements.AsEnumerable().Reverse()); - - return aggregated; - } - } + public virtual HoconValue Root { get; } /// /// Returns string representation of , allowing to include fallback values @@ -95,11 +92,7 @@ public string ToString(bool useFallbackValues) protected Config Copy() { //deep clone - return new Config - { - Fallback = Fallback?.Copy(), - Value = (HoconValue) Value.Clone(null) - }; + return new Config((HoconValue) Value.Clone(null), Fallback?.Copy()); } protected override HoconValue GetNode(HoconPath path, bool throwIfNotFound = false) @@ -144,14 +137,10 @@ public virtual Config WithFallback(Config fallback) { if (fallback == this) throw new ArgumentException("Config can not have itself as fallback", nameof(fallback)); - - var clone = Copy(); - - var current = clone; - while (current.Fallback != null) current = current.Fallback; - current.Fallback = fallback.Copy(); - - return clone; + + // If Fallback is not set - we will set it in new copy + // If Fallback was set - just use it, but with adding new fallback values + return new Config((HoconValue) Value.Clone(null), Fallback?.WithFallback(fallback) ?? fallback); } /// @@ -199,6 +188,24 @@ public override IEnumerable> AsEnumerable() used.Add(kvp.Key); } } + + /// + /// Performs aggregation of Value and all Fallbacks into single object + /// + private HoconValue GetRootValue() + { + var elements = new List(); + + for (var config = this; config != null; config = config.Fallback?.Copy()) + { + elements.AddRange(config.Value); + } + + var aggregated = new HoconValue(null); + aggregated.AddRange(elements.AsEnumerable().Reverse()); + + return aggregated; + } } ///