using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Chernobyl.Event;
using Chernobyl.Values;
namespace Chernobyl.Collections.Generic.Event
{
///
/// An that can represent another
/// (the "source") while still allowing the
/// source to be swapped out with another
/// at any time.
///
/// The type that is to be held in this instance.
public class SourceEventEnumerable : IEventEnumerable
{
///
/// Initializes a new instance of the class.
///
public SourceEventEnumerable()
: this(null)
{}
///
/// Initializes a new instance of the class.
///
/// The source of the items that are being enumerated
/// and the events that are raised. If null is specified then this
/// instance will be empty.
public SourceEventEnumerable(IEventEnumerable source)
{
Source = source;
// When ItemsAdded/ItemsRemoved is invoked we'll want to also invoke
// IEventEnumerable.ItemsAdded/IEventEnumerable.ItemsRemoved.
ItemsAdded += (sender, e) =>
{
if (_itemsAdded != null)
_itemsAdded(this, e);
};
ItemsRemoved += (sender, e) =>
{
if (_itemsRemoved != null)
_itemsRemoved(this, e);
};
}
///
/// The source of the items that are being enumerated and the events that
/// are raised. If null is specified then this instance will be
/// empty.
///
public IEventEnumerable Source
{
get { return _source; }
set
{
IEventEnumerable previousValue = _source;
_source = value;
if (previousValue != null)
{
previousValue.ItemsAdded -= OnSourceItemsAdded;
previousValue.ItemsRemoved -= OnSourceItemsRemoved;
}
if (_source != null)
{
_source.ItemsAdded += OnSourceItemsAdded;
_source.ItemsRemoved += OnSourceItemsRemoved;
}
}
}
///
/// 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;
///
/// Returns an enumerator that iterates through the collection.
///
///
/// A that can be used to iterate through
/// the collection.
///
public IEnumerator GetEnumerator()
{
return _source != null ? _source.GetEnumerator() : System.Linq.Enumerable.Empty().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.
///
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; }
}
///
/// An event handler that is invoked when the
/// instance's event is
/// raised.
///
/// The sender of the event.
/// The arguments containing the removed items.
void OnSourceItemsAdded(object sender, ItemsEventArgs e)
{
if (ItemsAdded != null)
ItemsAdded(this, e);
}
///
/// An event handler that is invoked when the
/// instance's event is
/// raised.
///
/// The sender of the event.
/// The arguments containing the removed items.
void OnSourceItemsRemoved(object sender, ItemsEventArgs e)
{
if (ItemsRemoved != null)
ItemsRemoved(this, e);
}
///
/// The backing field to .
///
IEventEnumerable _source;
///
/// The backing field to .
///
EventHandler _itemsAdded;
///
/// The backing field to .
///
EventHandler _itemsRemoved;
}
///
/// Utility methods that make use of .
///
public static class SourceEventEnumerable
{
///
/// Returns an that represents the
/// contained in
/// regardless of whether it actually exists (i.e. is null) or whether
/// the instance is swapped for another
/// at any point.
///
/// The type that is to be held in the
/// .
/// The type of
/// contained within
/// .
/// The instance whose value is to be represented
/// regardless of what value it is at any given point.
/// The that represents the
/// value contained within .
public static IEventEnumerable AsEventEnumerable(this IValue value)
where TEventEnumerable : IEventEnumerable
{
SourceEventEnumerable sourceEventEnumerable = new SourceEventEnumerable();
value.Provide += (sender, e) => sourceEventEnumerable.Source = e.NewValue;
return sourceEventEnumerable;
}
///
/// Performs the same task as
///
/// except this method is for instances deriving from
/// which are often used for collections of services in Chernobyl.
///
/// The type of
/// contained within
/// . This type must inherit from
/// with as its type.
/// The instance whose value is to be represented
/// regardless of what value it is at any given point.
/// The that represents the
/// value contained within .
public static IEventEnumerable