using System; using System.Collections.Generic; using Chernobyl.ComponentModel; namespace Chernobyl.Creation { /// /// An that holds a list of /// instances. When a creation is /// requested, this type will go down the list attempt to build the item /// using each . This type will return /// the first item successfully created from one of the /// . /// /// The type of the result. /// The type of the 1. public class FirstSuccessFactory : Builder, IFactory { /// /// Initializes a new instance of the /// class. /// /// The /// that are to be attempted in building of items. public FirstSuccessFactory(IEnumerable> selectors) { _selectors = selectors; } /// /// Constructs and/or configures an instance of type /// . When this method is invoked, /// will be raised before /// is invoked. /// /// The method that should be invoked when the /// instance has been created, when its creation was canceled, or when /// an error occurred during its creation. Note that this callback may /// be invoked on another thread. /// The first argument. /// /// The that can be used to control and /// track the creation/configuration of the instance. /// public ITask Create(CreationCompletedEventHandler callback, T1 arg1) { return new Task(this, _selectors.GetEnumerator(), callback, arg1); } /// /// Represents a creation task; handle the actual construction. /// class Task : ComponentModel.Task { /// /// Initializes a new instance of the class. /// /// The instance that spawned this /// . /// The instance that denotes the order in /// which the instances are to /// be tried. /// The method that should be invoked when /// the instance has been created, when its creation was canceled, /// or when an error occurred during its creation. Note that this /// callback may be invoked on another thread. /// The first argument provided to the /// instances at creation. public Task(FirstSuccessFactory factory, IEnumerator> selector, CreationCompletedEventHandler callback, T1 arg1) { _factory = factory; _selector = selector; _callback = callback; _arg1 = arg1; TryNextFactory(); } /// /// An event handler that is invoked when an /// finishes construction. /// /// The sender of the event. /// The /// instance containing the event data. void OnCreation(object sender, CreationEventArgs e) { if (e.IsGood()) _factory.ReportCreation(_callback, e); else TryNextFactory(); } /// /// Moves to the next and /// invokes the creation method on it. If no /// instances are left to try /// an error is reported. /// void TryNextFactory() { if (_selector.MoveNext()) _selector.Current.Create(OnCreation, _arg1); else { _factory.ReportCreation(_callback, new CreationEventArgs( new Exception("Unable to create the requested " + "item. No factories are available " + "which can produce the item."))); } } /// /// The instance that spawned this . /// readonly FirstSuccessFactory _factory; /// /// The instance that denotes the order in which the /// instances are to be tried. /// readonly IEnumerator> _selector; /// /// The method that should be invoked when the instance has been /// created, when its creation was canceled, or when an error /// occurred during its creation. Note that this callback may be /// invoked on another thread. /// readonly CreationCompletedEventHandler _callback; /// /// The first argument provided to the /// instances at creation. /// readonly T1 _arg1; } /// /// The that are to be attempted in /// building of items. /// readonly IEnumerable> _selectors; } }