DictionaryBase.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. //
  2. // System.Collections.DictionaryBase.cs
  3. //
  4. // Author:
  5. // Miguel de Icaza ([email protected])
  6. //
  7. // (C) Ximian, Inc. http://www.ximian.com
  8. //
  9. using System;
  10. namespace System.Collections {
  11. /// <summary>
  12. /// An abstract class that provides a simple way to monitor changes to a
  13. /// Hashtable. Derived classes overwrite one or more of the `On' methods
  14. /// to track the changes to the Hashtable.
  15. /// </summary>
  16. ///
  17. /// <remarks>
  18. /// This class is a base class that can simplify the development of
  19. /// strongly typed collections. The idea being that the insertion of elements
  20. /// into the Hashtable can be forced to be of a given type.
  21. ///
  22. /// The `On' members are protected and designed to be used only by derived
  23. /// classes.
  24. /// </remarks>
  25. [Serializable]
  26. public abstract class DictionaryBase : IDictionary, ICollection, IEnumerable {
  27. Hashtable dictionary;
  28. protected DictionaryBase ()
  29. {
  30. dictionary = new Hashtable ();
  31. }
  32. /// <summary>
  33. /// Clears the contents of the dictionary
  34. /// </summary>
  35. public void Clear ()
  36. {
  37. OnClear ();
  38. dictionary.Clear ();
  39. OnClearComplete ();
  40. }
  41. /// <summary>
  42. /// Returns the number of items in the dictionary
  43. /// </summary>
  44. public int Count {
  45. get {
  46. return dictionary.Count;
  47. }
  48. }
  49. /// <summary>
  50. /// The collection contained as an IDictionary
  51. /// </summary>
  52. protected IDictionary Dictionary {
  53. get {
  54. return dictionary;
  55. }
  56. }
  57. /// <summary>
  58. /// The internal Hashtable representation for this dictionary
  59. /// </summary>
  60. protected Hashtable InnerHashtable {
  61. get {
  62. return dictionary;
  63. }
  64. }
  65. /// <summary>
  66. /// Copies the contents of the Dictionary into the target array
  67. /// </summary>
  68. /// <param name="array">
  69. /// The array to copy the contents of the dictionary to. The
  70. /// array must have a zero-based indexing
  71. /// </param>
  72. /// <param name="index">
  73. /// Starting index within the array where to copy the objects
  74. /// to.
  75. /// </param>
  76. public void CopyTo (Array array, int index)
  77. {
  78. if (array == null)
  79. throw new ArgumentNullException ("array");
  80. if (index < 0)
  81. throw new ArgumentOutOfRangeException ("index must be possitive");
  82. if (array.Rank > 1)
  83. throw new ArgumentException ("array is multidimensional");
  84. int size = array.Length;
  85. if (index > size)
  86. throw new ArgumentException ("index is larger than array size");
  87. if (index + Count > size)
  88. throw new ArgumentException ("Copy will overlflow array");
  89. DoCopy (array, index);
  90. }
  91. /// <summary>
  92. /// Internal routine called by CopyTo to perform the actual
  93. /// copying of the data
  94. /// </summary>
  95. private void DoCopy (Array array, int index)
  96. {
  97. foreach (DictionaryEntry de in dictionary)
  98. array.SetValue (de, index++);
  99. }
  100. /// <summary>
  101. /// Returns an enumerator for the dictionary
  102. /// </summary>
  103. public IDictionaryEnumerator GetEnumerator ()
  104. {
  105. return dictionary.GetEnumerator ();
  106. }
  107. /// <summary>
  108. /// Hook invoked before the clear operation
  109. /// is performed on the DictionaryBase
  110. /// </summary>
  111. protected virtual void OnClear ()
  112. {
  113. }
  114. /// <summary>
  115. /// Hook invoked after the clear operation
  116. /// is performed on the DictionaryBase
  117. /// </summary>
  118. ///
  119. /// <remarks>
  120. /// The default implementation does nothing, derived classes
  121. /// can override this method to be notified of changes
  122. /// </remarks>
  123. protected virtual void OnClearComplete ()
  124. {
  125. }
  126. /// <summary>
  127. /// Hook invoked while fetching data from the DictionaryBase.
  128. /// </summary>
  129. ///
  130. /// <remarks>
  131. /// This method is provided as a simple way to override the values
  132. /// returned by the DictionaryBase.
  133. /// </remarks>
  134. ///
  135. /// <param name="key">Key of the object to retrieve</param>
  136. /// <param name="current_value">Current value of the object associated with
  137. /// <paramref name="key"/></param>
  138. protected virtual object OnGet (object key, object current_value)
  139. {
  140. return current_value;
  141. }
  142. /// <summary>
  143. /// Hook invoked before inserting data into the DictionaryBase.
  144. /// </summary>
  145. ///
  146. /// <remarks>
  147. /// Derived classes can override this method and perform some
  148. /// action before the <paramref name="current_value"/> is inserted
  149. /// into the dictionary.
  150. ///
  151. /// The default implementation does nothing, derived classes
  152. /// can override this method to be notified of changes
  153. /// </remarks>
  154. ///
  155. /// <param name="key">Key of the object to insert</param>
  156. /// <param name="current_value">Current value of the object associated with
  157. /// <paramref name="key"/></param>
  158. protected virtual void OnInsert (object key, object current_value)
  159. {
  160. }
  161. /// <summary>
  162. /// Hook invoked after inserting the data into the DictionaryBase
  163. /// </summary>
  164. ///
  165. /// <remarks>
  166. /// The default implementation does nothing, derived classes
  167. /// can override this method to be notified of changes
  168. /// </remarks>
  169. ///
  170. /// <param name="key">Key of the object to insert</param>
  171. /// <param name="current_value">Current value of the object associated with
  172. /// <paramref name="key"/></param>
  173. protected virtual void OnInsertComplete (object key, object current_value)
  174. {
  175. }
  176. /// <summary>
  177. /// Hook invoked before changing a value for a key in the DictionaryBase.
  178. /// </summary>
  179. ///
  180. /// <remarks>
  181. /// Derived classes can override this method and perform some
  182. /// action before the <paramref name="current_value"/> is changed
  183. /// in the dictionary.
  184. /// </remarks>
  185. ///
  186. /// <param name="key">Key of the object to change</param>
  187. /// <param name="current_value">Current value of the object associated with
  188. /// <paramref name="key"/></param>
  189. protected virtual void OnSet (object key, object current_value, object new_value)
  190. {
  191. }
  192. /// <summary>
  193. /// Hook invoked after changing a value for a key in the DictionaryBase.
  194. /// </summary>
  195. ///
  196. /// <remarks>
  197. /// The default implementation does nothing, derived classes
  198. /// can override this method to be notified of changes
  199. /// </remarks>
  200. ///
  201. /// <param name="key">Key of the object to change</param>
  202. /// <param name="current_value">Current value of the object associated with
  203. /// <paramref name="key"/></param>
  204. protected virtual void OnSetComplete (object key, object current_value, object new_value)
  205. {
  206. }
  207. /// <summary>
  208. /// Hook invoked before removing a key/value from the DictionaryBase.
  209. /// </summary>
  210. ///
  211. /// <remarks>
  212. /// Derived classes can override this method and perform some
  213. /// action before the <paramref name="current_value"/> is removed
  214. /// from the dictionary.
  215. /// </remarks>
  216. ///
  217. /// <param name="key">Key of the object to remove</param>
  218. /// <param name="current_value">Current value of the object associated with
  219. /// <paramref name="key"/></param>
  220. protected virtual void OnRemove (object key, object current_value)
  221. {
  222. }
  223. /// <summary>
  224. /// Hook invoked after removing a key/value from the DictionaryBase.
  225. /// </summary>
  226. ///
  227. /// <remarks>
  228. /// The default implementation does nothing, derived classes
  229. /// can override this method to be notified of changes.
  230. /// </remarks>
  231. ///
  232. /// <param name="key">Key of the object to remove</param>
  233. /// <param name="current_value">Current value of the object associated with
  234. /// <paramref name="key"/></param>
  235. protected virtual void OnRemoveComplete (object key, object current_value)
  236. {
  237. }
  238. /// <summary>
  239. /// Hook invoked after the value has been validated
  240. /// </summary>
  241. ///
  242. /// <remarks>
  243. /// The default implementation does nothing, derived classes
  244. /// can override this method to monitor the DictionaryBase.
  245. /// </remarks>
  246. ///
  247. /// <param name="key">Key of the object to retrieve</param>
  248. /// <param name="current_value">Current value of the object associated with
  249. /// <paramref name="key"/></param>
  250. protected virtual void OnValidate (object key, object current_value)
  251. {
  252. }
  253. bool IDictionary.IsFixedSize {
  254. get {
  255. return false;
  256. }
  257. }
  258. bool IDictionary.IsReadOnly {
  259. get {
  260. return false;
  261. }
  262. }
  263. object IDictionary.this [object key] {
  264. get {
  265. object value = dictionary [key];
  266. OnGet (key, value);
  267. return value;
  268. }
  269. set {
  270. if (dictionary.ContainsKey (key)){
  271. object current_value = dictionary [key];
  272. OnSet (key, current_value, value);
  273. dictionary [key] = value;
  274. OnSetComplete (key, current_value, value);
  275. } else {
  276. OnInsert (key, value);
  277. dictionary [key] = value;
  278. OnInsertComplete (key, value);
  279. }
  280. }
  281. }
  282. ICollection IDictionary.Keys {
  283. get {
  284. return dictionary.Keys;
  285. }
  286. }
  287. ICollection IDictionary.Values {
  288. get {
  289. return dictionary.Values;
  290. }
  291. }
  292. /// <summary>
  293. /// Adds a key/value pair to the dictionary.
  294. /// </summary>
  295. void IDictionary.Add (object key, object value)
  296. {
  297. OnInsert (key, value);
  298. dictionary.Add (key, value);
  299. OnInsertComplete (key, value);
  300. }
  301. /// <summary>
  302. /// Removes a Dictionary Entry based on its key
  303. /// </summary>
  304. void IDictionary.Remove (object key)
  305. {
  306. if (! dictionary.ContainsKey (key))
  307. return;
  308. object value = dictionary [key];
  309. OnRemove (key, value);
  310. dictionary.Remove (key);
  311. OnRemoveComplete (key, value);
  312. }
  313. /// <summary>
  314. /// Tests whether the dictionary contains an entry
  315. /// </summary>
  316. bool IDictionary.Contains (object key)
  317. {
  318. return dictionary.Contains (key);
  319. }
  320. bool ICollection.IsSynchronized {
  321. get {
  322. return dictionary.IsSynchronized;
  323. }
  324. }
  325. object ICollection.SyncRoot {
  326. get {
  327. return dictionary.SyncRoot;
  328. }
  329. }
  330. IEnumerator IEnumerable.GetEnumerator ()
  331. {
  332. return dictionary.GetEnumerator ();
  333. }
  334. }
  335. }