using System; using System.Collections.Generic; using Chernobyl.Collections.Generic.Event; using Chernobyl.Collections.Generic.Hierarchy; using Chernobyl.Event; using Chernobyl.Utility; namespace Chernobyl.Collections.Generic.Graph { /// /// A type used to maintain bi-directional connections between nodes in a /// graph. /// /// The vertice reference types that /// make up the types contained in the network. public class Connections : Collection where TNode : class { /// /// Initializes a new instance of the /// class. /// /// The instance whose connections are being /// held by this. /// The method used to get the connection /// from a /// type. This method will be used to add/remove the /// to/from the connected . /// Thrown if any of the parameters /// provided are null. public Connections(TNode connected, Func> getConnections) { connected.ThrowIfNull("parent"); getConnections.ThrowIfNull("getChildren"); _connected = connected; _getConnections = getConnections; _implementation = new DecoratingEventList(); _implementation.ItemsAdded += OnItemsAdded; _implementation.ItemsRemoved += OnItemsRemoved; } /// /// The implementation of this . /// protected override ICollection Implementation { get { return _implementation; } } /// /// Invoked when an item is added to this . /// This method ensures that the new /// intances are also connected to the . /// /// The sender of the event. /// The instance /// containing the event data. void OnItemsAdded(object sender, ItemsEventArgs e) { // If the parent node isn't already in this node, add it. foreach (TNode node in e.Items) { ICollection nodeConnections = _getConnections(node); if (nodeConnections.Contains(_connected) == false) nodeConnections.Add(_connected); } } /// /// Invoked when an item is remove from this . /// This method ensures that the old /// intances are also disconnected from the . /// /// The sender of the event. /// The instance /// containing the event data. void OnItemsRemoved(object sender, ItemsEventArgs e) { // Remove the parent connection from the foreach (TNode node in e.Items) _getConnections(node).Remove(_connected); } /// /// The instance whose connections are being held by this. /// readonly TNode _connected; /// /// The method used to get the connection /// from a type. This method will be used /// to add/remove the to/from the connected /// . /// readonly Func> _getConnections; /// /// The backing field to . /// readonly IEventCollection _implementation; } /// /// A type used to maintain bi-directional connections between /// instances in a graph. This type /// performs the same job as but is easier /// to create for types. /// public class NodeConnections : Connections { /// /// Initializes a new instance of the class. /// /// The instance whose connections are being /// held by this. public NodeConnections(INode connected) : base(connected, connection => connection.Connections) { } } }