using Chernobyl.Event;
using Chernobyl.Utility;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Chernobyl.Collections.Generic.Event
{
///
/// Combines two sequences into a single sequence.
///
/// The type of the elements of the input sequences.
public class Concatenation : IEventEnumerable
{
///
/// Initializes a new instance of the
/// class.
///
/// The first sequence to add to the second.
/// The second sequence to add to the first.
/// Thrown if
/// or is null.
public Concatenation(IEventEnumerable first,
IEventEnumerable second)
{
first.ThrowIfNull("first");
second.ThrowIfNull("second");
// IEventEnumerable.ItemsAdded should also raise the
// IEventEnumerable.ItemsAdded event.
ItemsAdded += (sender, args) =>
{
if (_itemsAdded != null)
_itemsAdded(sender, args);
};
// IEventEnumerable.ItemsRemoved should also raise the
// IEventEnumerable.ItemsRemoved event.
ItemsRemoved += (sender, args) =>
{
if (_itemsRemoved != null)
_itemsRemoved(sender, args);
};
_first = first;
_first.ItemsAdded += RaiseItemsAdded;
_first.ItemsRemoved += RaiseItemsRemoved;
_second = second;
_second.ItemsAdded += RaiseItemsAdded;
_second.ItemsRemoved += RaiseItemsRemoved;
}
///
/// Returns an enumerator that iterates through the collection.
///
///
/// A that can be used to iterate through
/// the collection.
///
public IEnumerator GetEnumerator()
{
return ((IEnumerable)_first).Concat(_second).GetEnumerator();
}
///
/// Returns an enumerator that iterates through a collection.
///
///
/// An object that can be used to iterate
/// through the collection.
///
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
///
/// An event that is raised right after items are added to this list.
///
public event EventHandler> ItemsAdded;
///
/// An event that is raised right after items are removed from this list.
///
public event EventHandler> ItemsRemoved;
///
/// An event that is raised right after items are added to this list.
///
event EventHandler IEventEnumerable.ItemsAdded
{
add { _itemsAdded += value; }
remove { _itemsAdded -= value; }
}
///
/// An event that is raised right after items are removed from this list.
///
event EventHandler IEventEnumerable.ItemsRemoved
{
add { _itemsRemoved += value; }
remove { _itemsRemoved -= value; }
}
///
/// Raises the event if it has event handlers.
///
/// The sender of the event. This parameter will
/// be replaced by this in the raised event.
/// The instance
/// containing the event data.
void RaiseItemsAdded(object sender, ItemsEventArgs e)
{
if (ItemsAdded != null)
ItemsAdded(this, e);
}
///
/// Raises the event if it has event handlers.
///
/// The sender of the event. This parameter will
/// be replaced by this in the raised event.
/// The instance
/// containing the event data.
void RaiseItemsRemoved(object sender, ItemsEventArgs e)
{
if (ItemsRemoved != null)
ItemsRemoved(this, e);
}
///
/// The first sequence to add to the second.
///
readonly IEventEnumerable _first;
///
/// The second sequence to add to the first.
///
readonly IEventEnumerable _second;
///
/// The backing field to .
///
EventHandler _itemsAdded;
///
/// The backing field to .
///
EventHandler _itemsRemoved;
}
///
/// Extension and utility methods for .
///
public static class ConcatenationExtensions
{
///
/// Combines two sequences into a single sequence.
///
/// The type of the elements of the input sequences.
/// The first sequence to add to the second.
/// The second sequence to add to the first.
/// An instance that contains the combined elements of the two
/// input sequences.
/// Thrown if
/// or is null.
public static IEventEnumerable Concat(this IEventEnumerable first,
IEventEnumerable second)
{
return new Concatenation(first, second);
}
///
/// Combines multiple sequences into a single sequence.
///
/// The type of the elements of the input sequences.
/// The sequences that are to be combined.
/// An instance that contains the combined elements of the
/// input sequences.
/// Thrown if
/// is null.
public static IEventEnumerable Concat(IEnumerable> sequences)
{
sequences.ThrowIfNull("sequences");
IEventEnumerable sequence;
using (IEnumerator> iter = sequences.GetEnumerator())
{
// If sequences contains no elements then we return an empty
// IEventEnumerable{T}.
sequence = iter.MoveNext() ?
iter.Current : DecoratingEventEnumerable.Empty;
while (iter.MoveNext())
{
IEventEnumerable previousSequence = sequence;
sequence = previousSequence.Concat(iter.Current);
}
}
return sequence;
}
}
}