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 int Count => _components.Count; /// public IReadOnlyDictionary Named => _namedComponents; /// public IReadOnlyList<(string SafeName, T Component)> WithSafeNames => _componentsWithSafeNames; /// public T this[int index] => _components[index]; /// public T this[string key] => _namedComponents[key]; /// public IEnumerator GetEnumerator() => _components.GetEnumerator(); /// IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_components).GetEnumerator(); /// /// The collection is locked. public void Add(string name, T component) { EnsureConfigurationNotLocked(); if (name != null) { if (name.Length == 0) throw new ArgumentException("Component name is empty.", nameof(name)); if (_namedComponents.ContainsKey(name)) throw new ArgumentException("Duplicate component name.", nameof(name)); } if (component == null) throw new ArgumentNullException(nameof(component)); if (_components.Contains(component)) throw new ArgumentException("Component has already been added.", nameof(component)); _components.Add(component); _componentsWithSafeNames.Add((name ?? $"<{component.GetType().Name}>", component)); if (name != null) _namedComponents.Add(name, component); } /// /// Locks the collection, preventing further additions. /// public void Lock() => LockConfiguration(); } }