using System; using System.Collections.Generic; using System.Linq; namespace Umbraco.Core.Composing { /// /// Implements a lazy collection builder. /// /// The type of the builder. /// The type of the collection. /// The type of the items. public abstract class LazyCollectionBuilderBase : CollectionBuilderBase where TBuilder : LazyCollectionBuilderBase where TCollection : class, IBuilderCollection { private readonly List>> _producers = new List>>(); private readonly List _excluded = new List(); protected abstract TBuilder This { get; } /// /// Clears all types in the collection. /// /// The builder. public TBuilder Clear() { Configure(types => { types.Clear(); _producers.Clear(); _excluded.Clear(); }); return This; } /// /// Adds a type to the collection. /// /// The type to add. /// The builder. public TBuilder Add() where T : TItem { Configure(types => { var type = typeof(T); if (types.Contains(type) == false) types.Add(type); }); return This; } /// /// Adds a type to the collection. /// /// The type to add. /// The builder. public TBuilder Add(Type type) { Configure(types => { EnsureType(type, "register"); if (types.Contains(type) == false) types.Add(type); }); return This; } /// /// Adds a types producer to the collection. /// /// The types producer. /// The builder. public TBuilder Add(Func> producer) { Configure(types => { _producers.Add(producer); }); return This; } /// /// Excludes a type from the collection. /// /// The type to exclude. /// The builder. public TBuilder Exclude() where T : TItem { Configure(types => { var type = typeof(T); if (_excluded.Contains(type) == false) _excluded.Add(type); }); return This; } /// /// Excludes a type from the collection. /// /// The type to exclude. /// The builder. public TBuilder Exclude(Type type) { Configure(types => { EnsureType(type, "exclude"); if (_excluded.Contains(type) == false) _excluded.Add(type); }); return This; } protected override IEnumerable GetRegisteringTypes(IEnumerable types) { return types .Union(_producers.SelectMany(x => x())) .Distinct() .Select(x => EnsureType(x, "register")) .Except(_excluded); } } }