using System; namespace Swan.Configuration { /// /// Base class for objects whose configuration may be locked, /// thus becoming read-only, at a certain moment in their lifetime. /// public abstract class ConfiguredObject { private readonly Object _syncRoot = new Object(); private Boolean _configurationLocked; /// /// Gets a value indicating whether s configuration has already been locked /// and has therefore become read-only. /// /// /// if the configuration is locked; otherwise, . /// /// protected Boolean ConfigurationLocked { get { lock(this._syncRoot) { return this._configurationLocked; } } } /// /// Locks this instance's configuration, preventing further modifications. /// /// /// Configuration locking must be enforced by derived classes /// by calling at the start /// of methods and property setters that could change the object's /// configuration. /// Immediately before locking the configuration, this method calls /// as a last chance to validate configuration data, and to lock the configuration of contained objects. /// /// protected void LockConfiguration() { lock(this._syncRoot) { if(this._configurationLocked) { return; } this.OnBeforeLockConfiguration(); this._configurationLocked = true; } } /// /// Called immediately before locking the configuration. /// /// protected virtual void OnBeforeLockConfiguration() { } /// /// Checks whether a module's configuration has become read-only /// and, if so, throws an . /// /// The configuration is locked. /// protected void EnsureConfigurationNotLocked() { if(this.ConfigurationLocked) { throw new InvalidOperationException($"Configuration of this {this.GetType().Name} instance is locked."); } } } }