using System;
using System.Collections;
using System.Collections.Generic;
namespace Wayne.Lib
{
///
/// A virtual list of refined objects.
///
///
///
public class RefinedList : IList where RefinedType : BaseType
{
#region RefinedEnumerator
private class RefinedEnumerator : IEnumerator
{
private IList baseList;
private int index;
private bool invalidated;
public event EventHandler OnDisposed;
public RefinedEnumerator(IList baseList)
{
this.baseList = baseList;
index = -1;
}
public RefinedType Current { get; private set; }
public void Dispose()
{
if (OnDisposed != null)
OnDisposed(this, EventArgs.Empty);
}
object IEnumerator.Current
{
get { return Current; }
}
public bool MoveNext()
{
if (invalidated)
throw new InvalidOperationException("The collection was modified after the enumerator was created.");
index++;
if (index < baseList.Count)
Current = (RefinedType)baseList[index];
return (index < baseList.Count);
}
public void Reset()
{
if (invalidated)
throw new InvalidOperationException("The collection was modified after the enumerator was created.");
index = -1;
}
public void Invalidate()
{
invalidated = true;
}
}
#endregion
#region Fields
private IList baseList;
private List refinedEnumerators = new List();
private object refinedEnumeratorSyncObj = new object();
#endregion
#region Construction
///
/// Constructor.
///
/// The base list (the actual list that holds the items, or even another RefinedList).
public RefinedList(IList baseList)
{
this.baseList = baseList;
}
#endregion
#region Properties
///
/// Gets the number of elements contained in the list.
///
public int Count
{
get { return baseList.Count; }
}
///
/// Gets a value indicating whether the list is readonly.
///
public bool IsReadOnly
{
get { return baseList.IsReadOnly; }
}
///
/// Gets or sets the element at the specified index.
///
/// The zero-based index of the element to get or set.
///
public RefinedType this[int index]
{
get { return (RefinedType)baseList[index]; }
set { baseList[index] = value; }
}
#endregion
#region List Methods
///
/// Determines the index of a specific item in the list.
///
/// The object to locate in the list.
///
public int IndexOf(RefinedType item)
{
return baseList.IndexOf(item);
}
///
/// Inserts an item to the list at the specified index.
///
/// The zero-based index at which item should be inserted.
///
public void Insert(int index, RefinedType item)
{
baseList.Insert(index, item);
InvalidateEnumerators();
}
///
/// Removes the list item at the specified index.
///
/// The object to insert into the list.
public void RemoveAt(int index)
{
baseList.RemoveAt(index);
InvalidateEnumerators();
}
///
/// Adds an item to the list.
///
/// The object to add to the list.
public void Add(RefinedType item)
{
baseList.Add(item);
InvalidateEnumerators();
}
///
/// Removes all items from the list.
///
public void Clear()
{
if (baseList.Count > 0)
InvalidateEnumerators();
baseList.Clear();
}
///
/// Determines whether the list contains a specific value.
///
/// The object to locate in the list.
///
public bool Contains(RefinedType item)
{
return baseList.Contains(item);
}
///
/// Copies the elements of the list to an Array, starting at a particular Array index.
///
/// The one-dimensional Array that is the destination of the elements copied from list. The Array must have zero-based indexing.
/// The zero-based index in array at which copying begins.
public void CopyTo(RefinedType[] array, int arrayIndex)
{
for (int i = 0; i < baseList.Count; i++)
array[i + arrayIndex] = (RefinedType)baseList[i];
}
///
/// Removes the first occurrence of a specific object from the list.
///
/// The object to remove from the list.
///
public bool Remove(RefinedType item)
{
if (baseList.Remove(item))
{
InvalidateEnumerators();
return true;
}
return false;
}
///
/// Adds the elements of the specified collection to the end of the list.
///
/// The collection whose elements should be added to the end of the list. The collection itself cannot be null, but it can contain elements that are null, if type RefinedType is a reference type.
public void AddRange(IEnumerable collection)
{
foreach (RefinedType item in collection)
baseList.Add(item);
InvalidateEnumerators();
}
#endregion
#region Enumerator Methods
///
/// Returns an enumerator that iterates through a collection.
///
///
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
///
/// Returns an enumerator that iterates through the collection.
///
///
public IEnumerator GetEnumerator()
{
lock (refinedEnumeratorSyncObj)
{
RefinedEnumerator refinedEnumerator = new RefinedEnumerator(baseList);
refinedEnumerator.OnDisposed += refinedEnumerator_OnDisposed;
refinedEnumerators.Add(refinedEnumerator);
return refinedEnumerator;
}
}
private void refinedEnumerator_OnDisposed(object sender, EventArgs e)
{
lock (refinedEnumeratorSyncObj)
{
refinedEnumerators.Remove((RefinedEnumerator)sender);
}
}
private void InvalidateEnumerators()
{
lock (refinedEnumeratorSyncObj)
{
foreach (RefinedEnumerator refinedEnumerator in refinedEnumerators)
refinedEnumerator.Invalidate();
}
}
#endregion
}
}