using System; using System.Collections; using System.Collections.Generic; using Swan.Configuration; namespace Swan.Collections { /// /// Implements a collection of components. /// Each component in the collection may be given a unique name for later retrieval. /// /// The type of components in the collection. /// public class ComponentCollection : ConfiguredObject, IComponentCollection { private readonly List _components = new List(); private readonly List<(String, T)> _componentsWithSafeNames = new List<(String, T)>(); private readonly Dictionary _namedComponents = new Dictionary(); /// public Int32 Count => this._components.Count; /// public IReadOnlyDictionary Named => this._namedComponents; /// public IReadOnlyList<(String SafeName, T Component)> WithSafeNames => this._componentsWithSafeNames; /// public T this[Int32 index] => this._components[index]; /// public T this[String key] => this._namedComponents[key]; /// public IEnumerator GetEnumerator() => this._components.GetEnumerator(); /// IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this._components).GetEnumerator(); /// /// The collection is locked. public void Add(String name, T component) { this.EnsureConfigurationNotLocked(); if(name != null) { if(name.Length == 0) { throw new ArgumentException("Component name is empty.", nameof(name)); } if(this._namedComponents.ContainsKey(name)) { throw new ArgumentException("Duplicate component name.", nameof(name)); } } if(component == null) { throw new ArgumentNullException(nameof(component)); } if(this._components.Contains(component)) { throw new ArgumentException("Component has already been added.", nameof(component)); } this._components.Add(component); this._componentsWithSafeNames.Add((name ?? $"<{component.GetType().Name}>", component)); if(name != null) { this._namedComponents.Add(name, component); } } /// /// Locks the collection, preventing further additions. /// public void Lock() => this.LockConfiguration(); } }