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;
}
}