扩展功能的 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("排序状态下不能使用");
            
ifthis.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);
        }


    }

posted on 2005-04-22 17:12  老翅寒暑  阅读(1215)  评论(1编辑  收藏  举报

导航