// // System.Collections.DictionaryBase.cs // // Author: // Miguel de Icaza (miguel@ximian.com) // // (C) Ximian, Inc. http://www.ximian.com // using System; namespace System.Collections { /// /// An abstract class that provides a simple way to monitor changes to a /// Hashtable. Derived classes overwrite one or more of the `On' methods /// to track the changes to the Hashtable. /// /// /// /// This class is a base class that can simplify the development of /// strongly typed collections. The idea being that the insertion of elements /// into the Hashtable can be forced to be of a given type. /// /// The `On' members are protected and designed to be used only by derived /// classes. /// [Serializable] public abstract class DictionaryBase : IDictionary, ICollection, IEnumerable { Hashtable dictionary; protected DictionaryBase () { dictionary = new Hashtable (); } /// /// Clears the contents of the dictionary /// public void Clear () { OnClear (); dictionary.Clear (); OnClearComplete (); } /// /// Returns the number of items in the dictionary /// public int Count { get { return dictionary.Count; } } /// /// The collection contained as an IDictionary /// protected IDictionary Dictionary { get { return this; } } /// /// The internal Hashtable representation for this dictionary /// protected Hashtable InnerHashtable { get { return dictionary; } } /// /// Copies the contents of the Dictionary into the target array /// /// /// The array to copy the contents of the dictionary to. The /// array must have a zero-based indexing /// /// /// Starting index within the array where to copy the objects /// to. /// public void CopyTo (Array array, int index) { if (array == null) throw new ArgumentNullException ("array"); if (index < 0) throw new ArgumentOutOfRangeException ("index must be possitive"); if (array.Rank > 1) throw new ArgumentException ("array is multidimensional"); int size = array.Length; if (index > size) throw new ArgumentException ("index is larger than array size"); if (index + Count > size) throw new ArgumentException ("Copy will overlflow array"); DoCopy (array, index); } /// /// Internal routine called by CopyTo to perform the actual /// copying of the data /// private void DoCopy (Array array, int index) { foreach (DictionaryEntry de in dictionary) array.SetValue (de, index++); } /// /// Returns an enumerator for the dictionary /// public IDictionaryEnumerator GetEnumerator () { return dictionary.GetEnumerator (); } /// /// Hook invoked before the clear operation /// is performed on the DictionaryBase /// protected virtual void OnClear () { } /// /// Hook invoked after the clear operation /// is performed on the DictionaryBase /// /// /// /// The default implementation does nothing, derived classes /// can override this method to be notified of changes /// protected virtual void OnClearComplete () { } /// /// Hook invoked while fetching data from the DictionaryBase. /// /// /// /// This method is provided as a simple way to override the values /// returned by the DictionaryBase. /// /// /// Key of the object to retrieve /// Current value of the object associated with /// protected virtual object OnGet (object key, object current_value) { return current_value; } /// /// Hook invoked before inserting data into the DictionaryBase. /// /// /// /// Derived classes can override this method and perform some /// action before the is inserted /// into the dictionary. /// /// The default implementation does nothing, derived classes /// can override this method to be notified of changes /// /// /// Key of the object to insert /// Current value of the object associated with /// protected virtual void OnInsert (object key, object current_value) { } /// /// Hook invoked after inserting the data into the DictionaryBase /// /// /// /// The default implementation does nothing, derived classes /// can override this method to be notified of changes /// /// /// Key of the object to insert /// Current value of the object associated with /// protected virtual void OnInsertComplete (object key, object current_value) { } /// /// Hook invoked before changing a value for a key in the DictionaryBase. /// /// /// /// Derived classes can override this method and perform some /// action before the is changed /// in the dictionary. /// /// /// Key of the object to change /// Current value of the object associated with /// protected virtual void OnSet (object key, object current_value, object new_value) { } /// /// Hook invoked after changing a value for a key in the DictionaryBase. /// /// /// /// The default implementation does nothing, derived classes /// can override this method to be notified of changes /// /// /// Key of the object to change /// Current value of the object associated with /// protected virtual void OnSetComplete (object key, object current_value, object new_value) { } /// /// Hook invoked before removing a key/value from the DictionaryBase. /// /// /// /// Derived classes can override this method and perform some /// action before the is removed /// from the dictionary. /// /// /// Key of the object to remove /// Current value of the object associated with /// protected virtual void OnRemove (object key, object current_value) { } /// /// Hook invoked after removing a key/value from the DictionaryBase. /// /// /// /// The default implementation does nothing, derived classes /// can override this method to be notified of changes. /// /// /// Key of the object to remove /// Current value of the object associated with /// protected virtual void OnRemoveComplete (object key, object current_value) { } /// /// Hook invoked after the value has been validated /// /// /// /// The default implementation does nothing, derived classes /// can override this method to monitor the DictionaryBase. /// /// /// Key of the object to retrieve /// Current value of the object associated with /// protected virtual void OnValidate (object key, object current_value) { } bool IDictionary.IsFixedSize { get { return false; } } bool IDictionary.IsReadOnly { get { return false; } } object IDictionary.this [object key] { get { OnGet (key, dictionary[key]); object value = dictionary [key]; return value; } set { OnValidate (key, value); object current_value = dictionary [key]; OnSet (key, current_value, value); dictionary [key] = value; try { OnSetComplete (key, current_value, value); } catch { dictionary [key] = current_value; throw; } } } ICollection IDictionary.Keys { get { return dictionary.Keys; } } ICollection IDictionary.Values { get { return dictionary.Values; } } /// /// Adds a key/value pair to the dictionary. /// void IDictionary.Add (object key, object value) { OnValidate (key, value); OnInsert (key, value); dictionary.Add (key, value); try { OnInsertComplete (key, value); } catch { dictionary.Remove(key); throw; } } /// /// Removes a Dictionary Entry based on its key /// void IDictionary.Remove (object key) { object value = dictionary [key]; OnValidate (key, value); OnRemove (key, value); dictionary.Remove (key); OnRemoveComplete (key, value); } /// /// Tests whether the dictionary contains an entry /// bool IDictionary.Contains (object key) { return dictionary.Contains (key); } bool ICollection.IsSynchronized { get { return dictionary.IsSynchronized; } } object ICollection.SyncRoot { get { return dictionary.SyncRoot; } } IEnumerator IEnumerable.GetEnumerator () { return dictionary.GetEnumerator (); } } }