// Copyright (C) Stichting Deltares 2016. All rights reserved. // // This file is part of Ringtoets. // // Ringtoets is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with this program. If not, see . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Collections.Generic; namespace Core.Common.Base { /// /// Class that implements in a way that a hierarchy of objects can be observed recursively. /// /// /// The root being observed by instances of this class can be dynamically changed. /// /// The type of objects to observe recursively. public class RecursiveObserver : IObserver, IDisposable where T : class, IObservable { private T rootObservable; private readonly Action updateObserverAction; private readonly Func> getChildObservables; private readonly IList observedObjects = new List(); /// /// Creates a new instance of the class. /// /// The action to perform on notifications coming from one of the items of the hierarchy of observed objects. /// The method used for recursively obtaining the objects to observe. public RecursiveObserver(Action updateObserverAction, Func> getChildObservables) { this.updateObserverAction = updateObserverAction; this.getChildObservables = getChildObservables; } /// /// Gets or sets the root object to observe. /// public T Observable { get { return rootObservable; } set { rootObservable = value; UpdateObservedObjects(); } } public void UpdateObserver() { updateObserverAction(); // Update the list of observed objects as observables might have been added/removed UpdateObservedObjects(); } private void UpdateObservedObjects() { // Detach from the currently observed objects foreach (var observedObject in observedObjects) { observedObject.Detach(this); } // Clear the list of observed objects observedObjects.Clear(); // If relevant, start observing objects again if (rootObservable != null) { foreach (var objectToObserve in GetObservablesRecursive(rootObservable)) { objectToObserve.Attach(this); observedObjects.Add(objectToObserve); } } } private IEnumerable GetObservablesRecursive(T observable) { var observables = new List { observable }; foreach (var childObservable in getChildObservables(observable)) { observables.AddRange(GetObservablesRecursive(childObservable)); } return observables; } public void Dispose() { Observable = null; } } }