扩展功能的 CollectionBaseEx
因为平时使用 System.Collections.CollectionBase 时候发现有些不足,故而作了一个扩展的 CollectionBaseEx,代码如下,因为注释较多,故不再解释。
/// <summary>
/// 增强的 CollectionBase ,支持排序,和更多的通知
/// </summary>
public class CollectionBaseEx : IList
{
private ArrayList m_InnerList;
private bool m_Duplicated; // 是否允许重复元素
private bool m_Sorted; // 是否允许排序
private IComparer m_Comparer; // 排序时候使用的比较器
private bool m_SingleCheck; // 是否在处理时候要处理单个元素,引发Include/Exclude事件
/// <summary>
/// 默认构造函数
/// </summary>
protected CollectionBaseEx()
{
m_InnerList = new ArrayList();
m_Duplicated = true;
m_Sorted = false;
m_Comparer = System.Collections.Comparer.Default;
m_SingleCheck = false;
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="duplicated">是否允许重复元素</param>
/// <param name="singleCheck">是否对每一个元素进行检查并发出通知</param>
/// <param name="sorted">对值进行排序</param>
/// <param name="comparer">比较器</param>
protected CollectionBaseEx(bool duplicated, bool singleCheck, bool sorted, IComparer comparer) : this()
{
m_Duplicated = duplicated;
m_Sorted = sorted;
m_Comparer = comparer;
m_SingleCheck = singleCheck;
}
/// <summary>
/// 操作接口,能够触发各种通知
/// </summary>
protected IList List { get { return this; } }
/// <summary>
/// 实际存放数据的容器
/// </summary>
protected ArrayList InnerList
{
get { return m_InnerList; }
set
{
if (value == null)
throw new ArgumentNullException("value can not be null", "value");
m_InnerList = value;
}
}
/// <summary>
/// 允许重复元素
/// </summary>
protected bool Duplicated { get { return m_Duplicated; } set { m_Duplicated = value; } }
/// <summary>
/// 排序
/// </summary>
protected bool Sorted { get { return m_Sorted; } set { m_Sorted = value; } }
/// <summary>
/// 对每一个元素进行检查并发出通知
/// </summary>
protected bool SingleCheck { get { return m_SingleCheck; } set { m_SingleCheck = value; } }
/// <summary>
/// 比较器
/// </summary>
protected IComparer Comparer { get { return m_Comparer; } set { m_Comparer = value; } }
#region callback
/// <summary>
/// 清除所有元素之前的通知
/// </summary>
protected virtual void OnClear(){}
/// <summary>
/// 所有元素清除成功之后的通知
/// </summary>
protected virtual void OnClearComplete(){}
/// <summary>
/// 插入元素之前的通知
/// </summary>
/// <param name="index">元素插入位置</param>
/// <param name="value">插入的值</param>
protected virtual void OnInsert(int index, object value){}
/// <summary>
/// 元素插入成功之后的通知
/// </summary>
/// <param name="index">元素插入位置</param>
/// <param name="value">插入的值</param>
protected virtual void OnInsertComplete(int index, object value){}
/// <summary>
/// 删除元素之前的通知
/// </summary>
/// <param name="index">要删除元素的位置</param>
/// <param name="value">要删除的元素</param>
protected virtual void OnRemove(int index, object value){}
/// <summary>
/// 删除元素之后的通知
/// </summary>
/// <param name="index">要删除元素的位置</param>
/// <param name="value">要删除的元素</param>
protected virtual void OnRemoveComplete(int index, object value){}
/// <summary>
/// 设置元素的值之前的通知
/// </summary>
/// <param name="index">元素的位置</param>
/// <param name="oldValue">该位置的当前的值</param>
/// <param name="newValue">将要存放到该位置的新值</param>
/// <remarks>如果<see cref="Sorted"/>为真,则设置成功之后的元素会移动到正确的位置上去</remarks>
protected virtual void OnSet(int index, object oldValue, object newValue){}
/// <summary>
/// 设置元素的值成功之后的通知
/// </summary>
/// <param name="index">元素位置</param>
/// <param name="oldValue">该位置以前的值</param>
/// <param name="newValue">该位置当前的值</param>
/// <remarks>如果<see cref="Sorted"/>为真,则设置成功之后的元素会移动到正确的位置上去</remarks>
protected virtual void OnSetComplete(int index, object oldValue, object newValue){}
/// <summary>
/// 通知对元素进行正确性检查
/// </summary>
/// <param name="value">将要存放的值</param>
protected virtual void OnValidate(object value){}
/// <summary>
/// 将要把元素存放到容器之前的通知
/// </summary>
/// <param name="value">将要存放的值</param>
protected virtual void OnInclude(object value){}
/// <summary>
/// 将要把元素从容器中脱离之前的通知
/// </summary>
/// <param name="value">将要脱离容器的值</param>
protected virtual void OnExclude(object value){}
#endregion
#region internal logic
private void BeforeClear()
{
if( m_SingleCheck )
{
int index = 0;
try
{
while( index < m_InnerList.Count)
{
OnExclude(m_InnerList[index]);
++ index;
}
}
catch(Exception)
{
while( --index >= 0 )
OnInclude(m_InnerList[index]);
throw;
}
}
OnClear();
}
private void AfterClearComplete()
{
OnClearComplete();
}
private void BeforeInsert(int index, object value)
{
if( m_Sorted )
throw new InvalidOperationException("排序状态下不能使用");
if( this.m_SingleCheck )
OnInclude(value);
OnInsert(index, value);
}
private void AfterInsertComplete(int index, object value)
{
OnInsertComplete(index, value);
}
private void BeforeRemove(int index, object value)
{
if( m_SingleCheck )
OnExclude(value);
OnRemove(index, value);
}
private void AfterRemoveComplete(int index, object value)
{
OnRemoveComplete(index, value);
}
private void BeforeSet(int index, object oldValue, object newValue)
{
if( m_SingleCheck )
OnInclude(newValue);
OnSet(index, oldValue, newValue);
}
private void AfterSetComplete(int index, object oldValue, object newValue)
{
if( m_SingleCheck )
OnExclude(oldValue);
OnSetComplete(index, oldValue, newValue);
}
private void CheckValidate(object value)
{
if (value == null)
throw new ArgumentNullException("value can not be null", "value");
if( !Duplicated
&& (( !m_Sorted && m_InnerList.IndexOf(value) != -1 )
|| (m_Sorted && m_InnerList.BinarySearch(value, m_Comparer) >= 0)
))
throw new ArgumentException("object exists");
OnValidate(value);
}
#endregion
#region IList 成员
bool IList.IsReadOnly { get { return m_InnerList.IsReadOnly; } }
object IList.this[int index]
{
get { return m_InnerList[index]; }
set
{
CheckValidate(value);
object old = m_InnerList[index];
this.BeforeSet(index, old, value);
m_InnerList[index] = value;
try
{
this.AfterSetComplete(index, old, value);
if( m_Sorted ) // 移动到正确位置
{
m_InnerList.RemoveAt(index);
int pos = m_InnerList.BinarySearch(value, m_Comparer);
if( pos < 0 ) pos = ~pos;
m_InnerList.Insert(pos, value);
}
}
catch (Exception)
{
m_InnerList[index] = old;
throw;
}
}
}
public void RemoveAt(int index)
{
object obj = m_InnerList[index];
this.BeforeRemove(index, obj);
m_InnerList.RemoveAt(index);
this.AfterRemoveComplete(index, obj);
}
void IList.Insert(int index, object value)
{
CheckValidate(value);
this.BeforeInsert(index, value);
m_InnerList.Insert(index, value);
try
{
this.AfterInsertComplete(index, value);
}
catch (Exception)
{
m_InnerList.RemoveAt(index);
throw;
}
}
void IList.Remove(object value)
{
int index = m_InnerList.IndexOf(value);
if( index < 0 )
throw new ArgumentException("object not found");
this.BeforeRemove(index, value);
m_InnerList.Remove(value);
this.AfterRemoveComplete(index, value);
}
bool IList.Contains(object value)
{
return m_InnerList.Contains(value);
}
public void Clear()
{
this.BeforeClear();
m_InnerList.Clear();
this.AfterClearComplete();
}
int IList.IndexOf(object value)
{
return m_InnerList.IndexOf(value);
}
int IList.Add(object value)
{
CheckValidate(value);
int index = m_InnerList.Count;
if( m_Sorted )
{
index = m_InnerList.BinarySearch(value, m_Comparer);
if( index < 0 ) index = ~index;
}
this.BeforeInsert(index, value);
if( !m_Sorted )
index = m_InnerList.Add(value);
else
m_InnerList.Insert(index, value);
try
{
this.AfterInsertComplete(index, value);
}
catch (Exception)
{
m_InnerList.RemoveAt(index);
throw;
}
return index;
}
bool IList.IsFixedSize { get { return m_InnerList.IsFixedSize; } }
#endregion
#region ICollection 成员
bool ICollection.IsSynchronized { get { return m_InnerList.IsSynchronized; } }
public int Count { get { return m_InnerList.Count; } }
void ICollection.CopyTo(Array array, int index)
{
m_InnerList.CopyTo(array, index);
}
object ICollection.SyncRoot { get { return m_InnerList.SyncRoot; } }
#endregion
#region IEnumerable 成员
public IEnumerator GetEnumerator()
{
return m_InnerList.GetEnumerator();
}
#endregion
public IEnumerator GetEnumerator(int index, int count)
{
return m_InnerList.GetEnumerator(index, count);
}
}
/// 增强的 CollectionBase ,支持排序,和更多的通知
/// </summary>
public class CollectionBaseEx : IList
{
private ArrayList m_InnerList;
private bool m_Duplicated; // 是否允许重复元素
private bool m_Sorted; // 是否允许排序
private IComparer m_Comparer; // 排序时候使用的比较器
private bool m_SingleCheck; // 是否在处理时候要处理单个元素,引发Include/Exclude事件
/// <summary>
/// 默认构造函数
/// </summary>
protected CollectionBaseEx()
{
m_InnerList = new ArrayList();
m_Duplicated = true;
m_Sorted = false;
m_Comparer = System.Collections.Comparer.Default;
m_SingleCheck = false;
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="duplicated">是否允许重复元素</param>
/// <param name="singleCheck">是否对每一个元素进行检查并发出通知</param>
/// <param name="sorted">对值进行排序</param>
/// <param name="comparer">比较器</param>
protected CollectionBaseEx(bool duplicated, bool singleCheck, bool sorted, IComparer comparer) : this()
{
m_Duplicated = duplicated;
m_Sorted = sorted;
m_Comparer = comparer;
m_SingleCheck = singleCheck;
}
/// <summary>
/// 操作接口,能够触发各种通知
/// </summary>
protected IList List { get { return this; } }
/// <summary>
/// 实际存放数据的容器
/// </summary>
protected ArrayList InnerList
{
get { return m_InnerList; }
set
{
if (value == null)
throw new ArgumentNullException("value can not be null", "value");
m_InnerList = value;
}
}
/// <summary>
/// 允许重复元素
/// </summary>
protected bool Duplicated { get { return m_Duplicated; } set { m_Duplicated = value; } }
/// <summary>
/// 排序
/// </summary>
protected bool Sorted { get { return m_Sorted; } set { m_Sorted = value; } }
/// <summary>
/// 对每一个元素进行检查并发出通知
/// </summary>
protected bool SingleCheck { get { return m_SingleCheck; } set { m_SingleCheck = value; } }
/// <summary>
/// 比较器
/// </summary>
protected IComparer Comparer { get { return m_Comparer; } set { m_Comparer = value; } }
#region callback
/// <summary>
/// 清除所有元素之前的通知
/// </summary>
protected virtual void OnClear(){}
/// <summary>
/// 所有元素清除成功之后的通知
/// </summary>
protected virtual void OnClearComplete(){}
/// <summary>
/// 插入元素之前的通知
/// </summary>
/// <param name="index">元素插入位置</param>
/// <param name="value">插入的值</param>
protected virtual void OnInsert(int index, object value){}
/// <summary>
/// 元素插入成功之后的通知
/// </summary>
/// <param name="index">元素插入位置</param>
/// <param name="value">插入的值</param>
protected virtual void OnInsertComplete(int index, object value){}
/// <summary>
/// 删除元素之前的通知
/// </summary>
/// <param name="index">要删除元素的位置</param>
/// <param name="value">要删除的元素</param>
protected virtual void OnRemove(int index, object value){}
/// <summary>
/// 删除元素之后的通知
/// </summary>
/// <param name="index">要删除元素的位置</param>
/// <param name="value">要删除的元素</param>
protected virtual void OnRemoveComplete(int index, object value){}
/// <summary>
/// 设置元素的值之前的通知
/// </summary>
/// <param name="index">元素的位置</param>
/// <param name="oldValue">该位置的当前的值</param>
/// <param name="newValue">将要存放到该位置的新值</param>
/// <remarks>如果<see cref="Sorted"/>为真,则设置成功之后的元素会移动到正确的位置上去</remarks>
protected virtual void OnSet(int index, object oldValue, object newValue){}
/// <summary>
/// 设置元素的值成功之后的通知
/// </summary>
/// <param name="index">元素位置</param>
/// <param name="oldValue">该位置以前的值</param>
/// <param name="newValue">该位置当前的值</param>
/// <remarks>如果<see cref="Sorted"/>为真,则设置成功之后的元素会移动到正确的位置上去</remarks>
protected virtual void OnSetComplete(int index, object oldValue, object newValue){}
/// <summary>
/// 通知对元素进行正确性检查
/// </summary>
/// <param name="value">将要存放的值</param>
protected virtual void OnValidate(object value){}
/// <summary>
/// 将要把元素存放到容器之前的通知
/// </summary>
/// <param name="value">将要存放的值</param>
protected virtual void OnInclude(object value){}
/// <summary>
/// 将要把元素从容器中脱离之前的通知
/// </summary>
/// <param name="value">将要脱离容器的值</param>
protected virtual void OnExclude(object value){}
#endregion
#region internal logic
private void BeforeClear()
{
if( m_SingleCheck )
{
int index = 0;
try
{
while( index < m_InnerList.Count)
{
OnExclude(m_InnerList[index]);
++ index;
}
}
catch(Exception)
{
while( --index >= 0 )
OnInclude(m_InnerList[index]);
throw;
}
}
OnClear();
}
private void AfterClearComplete()
{
OnClearComplete();
}
private void BeforeInsert(int index, object value)
{
if( m_Sorted )
throw new InvalidOperationException("排序状态下不能使用");
if( this.m_SingleCheck )
OnInclude(value);
OnInsert(index, value);
}
private void AfterInsertComplete(int index, object value)
{
OnInsertComplete(index, value);
}
private void BeforeRemove(int index, object value)
{
if( m_SingleCheck )
OnExclude(value);
OnRemove(index, value);
}
private void AfterRemoveComplete(int index, object value)
{
OnRemoveComplete(index, value);
}
private void BeforeSet(int index, object oldValue, object newValue)
{
if( m_SingleCheck )
OnInclude(newValue);
OnSet(index, oldValue, newValue);
}
private void AfterSetComplete(int index, object oldValue, object newValue)
{
if( m_SingleCheck )
OnExclude(oldValue);
OnSetComplete(index, oldValue, newValue);
}
private void CheckValidate(object value)
{
if (value == null)
throw new ArgumentNullException("value can not be null", "value");
if( !Duplicated
&& (( !m_Sorted && m_InnerList.IndexOf(value) != -1 )
|| (m_Sorted && m_InnerList.BinarySearch(value, m_Comparer) >= 0)
))
throw new ArgumentException("object exists");
OnValidate(value);
}
#endregion
#region IList 成员
bool IList.IsReadOnly { get { return m_InnerList.IsReadOnly; } }
object IList.this[int index]
{
get { return m_InnerList[index]; }
set
{
CheckValidate(value);
object old = m_InnerList[index];
this.BeforeSet(index, old, value);
m_InnerList[index] = value;
try
{
this.AfterSetComplete(index, old, value);
if( m_Sorted ) // 移动到正确位置
{
m_InnerList.RemoveAt(index);
int pos = m_InnerList.BinarySearch(value, m_Comparer);
if( pos < 0 ) pos = ~pos;
m_InnerList.Insert(pos, value);
}
}
catch (Exception)
{
m_InnerList[index] = old;
throw;
}
}
}
public void RemoveAt(int index)
{
object obj = m_InnerList[index];
this.BeforeRemove(index, obj);
m_InnerList.RemoveAt(index);
this.AfterRemoveComplete(index, obj);
}
void IList.Insert(int index, object value)
{
CheckValidate(value);
this.BeforeInsert(index, value);
m_InnerList.Insert(index, value);
try
{
this.AfterInsertComplete(index, value);
}
catch (Exception)
{
m_InnerList.RemoveAt(index);
throw;
}
}
void IList.Remove(object value)
{
int index = m_InnerList.IndexOf(value);
if( index < 0 )
throw new ArgumentException("object not found");
this.BeforeRemove(index, value);
m_InnerList.Remove(value);
this.AfterRemoveComplete(index, value);
}
bool IList.Contains(object value)
{
return m_InnerList.Contains(value);
}
public void Clear()
{
this.BeforeClear();
m_InnerList.Clear();
this.AfterClearComplete();
}
int IList.IndexOf(object value)
{
return m_InnerList.IndexOf(value);
}
int IList.Add(object value)
{
CheckValidate(value);
int index = m_InnerList.Count;
if( m_Sorted )
{
index = m_InnerList.BinarySearch(value, m_Comparer);
if( index < 0 ) index = ~index;
}
this.BeforeInsert(index, value);
if( !m_Sorted )
index = m_InnerList.Add(value);
else
m_InnerList.Insert(index, value);
try
{
this.AfterInsertComplete(index, value);
}
catch (Exception)
{
m_InnerList.RemoveAt(index);
throw;
}
return index;
}
bool IList.IsFixedSize { get { return m_InnerList.IsFixedSize; } }
#endregion
#region ICollection 成员
bool ICollection.IsSynchronized { get { return m_InnerList.IsSynchronized; } }
public int Count { get { return m_InnerList.Count; } }
void ICollection.CopyTo(Array array, int index)
{
m_InnerList.CopyTo(array, index);
}
object ICollection.SyncRoot { get { return m_InnerList.SyncRoot; } }
#endregion
#region IEnumerable 成员
public IEnumerator GetEnumerator()
{
return m_InnerList.GetEnumerator();
}
#endregion
public IEnumerator GetEnumerator(int index, int count)
{
return m_InnerList.GetEnumerator(index, count);
}
}
公众号:老翅寒暑