2 // System.Web.UI.WebControls.OrderedDictionary.cs
\r
5 // Lluis Sanchez Gual (lluis@novell.com)
\r
7 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
\r
9 // Permission is hereby granted, free of charge, to any person obtaining
\r
10 // a copy of this software and associated documentation files (the
\r
11 // "Software"), to deal in the Software without restriction, including
\r
12 // without limitation the rights to use, copy, modify, merge, publish,
\r
13 // distribute, sublicense, and/or sell copies of the Software, and to
\r
14 // permit persons to whom the Software is furnished to do so, subject to
\r
15 // the following conditions:
\r
17 // The above copyright notice and this permission notice shall be
\r
18 // included in all copies or substantial portions of the Software.
\r
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
29 using System.Runtime.Serialization;
\r
31 namespace System.Collections.Specialized
\r
34 public class OrderedDictionary : IOrderedDictionary, IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback
\r
39 int initialCapacity;
\r
40 SerializationInfo serializationInfo;
\r
41 IEqualityComparer comparer;
\r
43 public OrderedDictionary ()
\r
45 list = new ArrayList ();
\r
46 hash = new Hashtable ();
\r
49 public OrderedDictionary (int capacity)
\r
51 initialCapacity = (capacity < 0) ? 0 : capacity;
\r
52 list = new ArrayList (initialCapacity);
\r
53 hash = new Hashtable (initialCapacity);
\r
56 public OrderedDictionary (IEqualityComparer comparer)
\r
58 list = new ArrayList ();
\r
59 hash = new Hashtable (comparer);
\r
60 this.comparer = comparer;
\r
63 public OrderedDictionary (int capacity, IEqualityComparer comparer)
\r
65 initialCapacity = (capacity < 0) ? 0 : capacity;
\r
66 list = new ArrayList (initialCapacity);
\r
67 hash = new Hashtable (initialCapacity, comparer);
\r
68 this.comparer = comparer;
\r
71 protected OrderedDictionary (SerializationInfo info, StreamingContext context)
\r
73 serializationInfo = info;
\r
76 protected virtual void OnDeserialization (object sender)
\r
78 ((IDeserializationCallback) this).OnDeserialization (sender);
\r
81 void IDeserializationCallback.OnDeserialization (object sender)
\r
83 if (serializationInfo == null)
\r
86 comparer = (IEqualityComparer) serializationInfo.GetValue ("KeyComparer", typeof (IEqualityComparer));
\r
87 readOnly = serializationInfo.GetBoolean ("ReadOnly");
\r
88 initialCapacity = serializationInfo.GetInt32 ("InitialCapacity");
\r
91 list = new ArrayList ();
\r
95 hash = new Hashtable (comparer);
\r
96 object[] array = (object[]) serializationInfo.GetValue ("ArrayList", typeof(object[]));
\r
97 foreach (DictionaryEntry de in array) {
\r
98 hash.Add (de.Key, de.Value);
\r
103 public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
\r
106 throw new ArgumentNullException ("info");
\r
108 info.AddValue ("KeyComparer", comparer, typeof (IEqualityComparer));
\r
109 info.AddValue ("ReadOnly", readOnly);
\r
110 info.AddValue ("InitialCapacity", initialCapacity);
\r
112 object[] array = new object [hash.Count];
\r
113 hash.CopyTo (array, 0);
\r
114 info.AddValue ("ArrayList", array);
\r
117 IEnumerator IEnumerable.GetEnumerator()
\r
119 return list.GetEnumerator ();
\r
128 bool ICollection.IsSynchronized {
\r
130 return list.IsSynchronized;
\r
134 object ICollection.SyncRoot {
\r
136 return list.SyncRoot;
\r
140 public void CopyTo (Array array, int index)
\r
142 list.CopyTo (array, index);
\r
145 bool IDictionary.IsFixedSize {
\r
151 public bool IsReadOnly
\r
158 public object this [object key]
\r
160 get { return hash [key]; }
\r
163 if (hash.Contains (key)) {
\r
164 int i = FindListEntry (key);
\r
165 list [i] = new DictionaryEntry (key, value);
\r
167 list.Add (new DictionaryEntry (key, value));
\r
169 hash [key] = value;
\r
173 public object this [int index]
\r
175 get { return ((DictionaryEntry) list [index]).Value; }
\r
178 DictionaryEntry de = (DictionaryEntry) list [index];
\r
180 // update (even on the list) isn't automatic
\r
182 hash [de.Key] = value;
\r
186 public ICollection Keys
\r
189 return new OrderedCollection (list, true);
\r
193 public ICollection Values
\r
196 return new OrderedCollection (list, false);
\r
200 public void Add (object key, object value)
\r
203 hash.Add (key, value);
\r
204 list.Add (new DictionaryEntry (key, value));
\r
207 public void Clear()
\r
214 public bool Contains (object key)
\r
216 return hash.Contains (key);
\r
219 public virtual IDictionaryEnumerator GetEnumerator()
\r
221 return new OrderedEntryCollectionEnumerator (list.GetEnumerator ());
\r
224 public void Remove (object key)
\r
228 if (hash.Contains (key)) {
\r
230 int i = FindListEntry (key);
\r
235 int FindListEntry (object key)
\r
237 for (int n=0; n<list.Count; n++) {
\r
238 DictionaryEntry de = (DictionaryEntry) list [n];
\r
239 if (comparer != null ? comparer.Equals(de.Key, key) : de.Key.Equals(key))
\r
248 throw new NotSupportedException ("Collection is read only");
\r
251 public OrderedDictionary AsReadOnly ()
\r
253 OrderedDictionary od = new OrderedDictionary ();
\r
256 od.comparer = comparer;
\r
257 od.readOnly = true;
\r
261 public void Insert (int index, object key, object value)
\r
264 hash.Add (key, value);
\r
265 list.Insert (index, new DictionaryEntry (key, value));
\r
268 public void RemoveAt (int index)
\r
271 DictionaryEntry entry = (DictionaryEntry) list [index];
\r
272 list.RemoveAt (index);
\r
273 hash.Remove (entry.Key);
\r
276 private class OrderedEntryCollectionEnumerator : IEnumerator, IDictionaryEnumerator
\r
278 IEnumerator listEnumerator;
\r
280 public OrderedEntryCollectionEnumerator (IEnumerator listEnumerator)
\r
282 this.listEnumerator = listEnumerator;
\r
285 public bool MoveNext()
\r
287 return listEnumerator.MoveNext ();
\r
290 public void Reset()
\r
292 listEnumerator.Reset ();
\r
295 public object Current
\r
297 get { return listEnumerator.Current; }
\r
300 public DictionaryEntry Entry
\r
302 get { return (DictionaryEntry) listEnumerator.Current; }
\r
307 get { return Entry.Key; }
\r
310 public object Value
\r
312 get { return Entry.Value; }
\r
316 private class OrderedCollection : ICollection
\r
318 private ArrayList list;
\r
319 private bool isKeyList;
\r
321 public OrderedCollection (ArrayList list, bool isKeyList)
\r
324 this.isKeyList = isKeyList;
\r
333 public bool IsSynchronized
\r
340 public object SyncRoot
\r
343 return list.SyncRoot;
\r
347 public void CopyTo (Array array, int index)
\r
349 for (int n=0; n<list.Count; n++) {
\r
350 DictionaryEntry de = (DictionaryEntry) list [n];
\r
351 if (isKeyList) array.SetValue (de.Key, index + n);
\r
352 else array.SetValue (de.Value, index + n);
\r
356 public IEnumerator GetEnumerator()
\r
358 return new OrderedCollectionEnumerator (list.GetEnumerator (), isKeyList);
\r
361 private class OrderedCollectionEnumerator : IEnumerator
\r
363 private bool isKeyList;
\r
364 IEnumerator listEnumerator;
\r
366 public OrderedCollectionEnumerator (IEnumerator listEnumerator, bool isKeyList)
\r
368 this.listEnumerator = listEnumerator;
\r
369 this.isKeyList = isKeyList;
\r
372 public object Current
\r
375 DictionaryEntry entry = (DictionaryEntry) listEnumerator.Current;
\r
376 return isKeyList ? entry.Key : entry.Value;
\r
380 public bool MoveNext()
\r
382 return listEnumerator.MoveNext ();
\r
385 public void Reset()
\r
387 listEnumerator.Reset ();
\r