-using System;\r
-using System.Collections;\r
-using System.Runtime.Serialization;\r
-\r
-#if NO_SYSTEM_DLL\r
-namespace System.Collections.Specialized\r
-{\r
- [Serializable]\r
- public abstract class NameObjectCollectionBase : ICollection, IEnumerable, ISerializable, IDeserializationCallback\r
- {\r
- private Hashtable m_ItemsContainer;\r
- /// <summary>\r
- /// Extends Hashtable based Items container to support storing null-key pairs\r
- /// </summary>\r
- private _Item m_NullKeyItem;\r
- private ArrayList m_ItemsArray;\r
- private IHashCodeProvider m_hashprovider;\r
- private IComparer m_comparer;\r
- private int m_defCapacity;\r
- private bool m_readonly;\r
- SerializationInfo infoCopy;\r
- private KeysCollection keyscoll;\r
-#if NET_2_0\r
- private IEqualityComparer equality_comparer;\r
-\r
- internal IEqualityComparer EqualityComparer {\r
- get { return equality_comparer; }\r
- }\r
-#endif\r
- internal IComparer Comparer\r
- {\r
- get { return m_comparer; }\r
- }\r
-\r
- internal IHashCodeProvider HashCodeProvider\r
- {\r
- get { return m_hashprovider; }\r
- }\r
-\r
- internal class _Item\r
- {\r
- public string key;\r
- public object value;\r
- public _Item(string key, object value)\r
- {\r
- this.key = key;\r
- this.value = value;\r
- }\r
- }\r
- /// <summary>\r
- /// Implements IEnumerable interface for KeysCollection\r
- /// </summary>\r
- [Serializable]\r
- internal class _KeysEnumerator : IEnumerator\r
- {\r
- private NameObjectCollectionBase m_collection;\r
- private int m_position;\r
-\r
- internal _KeysEnumerator(NameObjectCollectionBase collection)\r
- {\r
- m_collection = collection;\r
- Reset();\r
- }\r
- public object Current\r
- {\r
-\r
- get\r
- {\r
- if ((m_position < m_collection.Count) || (m_position < 0))\r
- return m_collection.BaseGetKey(m_position);\r
- else\r
- throw new InvalidOperationException();\r
- }\r
-\r
- }\r
- public bool MoveNext()\r
- {\r
- return ((++m_position) < m_collection.Count);\r
- }\r
- public void Reset()\r
- {\r
- m_position = -1;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// SDK: Represents a collection of the String keys of a collection.\r
- /// </summary>\r
- [Serializable]\r
- public class KeysCollection : ICollection, IEnumerable\r
- {\r
- private NameObjectCollectionBase m_collection;\r
-\r
- internal KeysCollection(NameObjectCollectionBase collection)\r
- {\r
- this.m_collection = collection;\r
- }\r
-\r
- public virtual string Get(int index)\r
- {\r
- return m_collection.BaseGetKey(index);\r
- }\r
-\r
- // ICollection methods -----------------------------------\r
- void ICollection.CopyTo(Array array, int arrayIndex)\r
- {\r
- ArrayList items = m_collection.m_ItemsArray;\r
-#if NET_2_0\r
- if (null == array)\r
- throw new ArgumentNullException ("array");\r
-\r
- if (arrayIndex < 0)\r
- throw new ArgumentOutOfRangeException ("arrayIndex");\r
-\r
- if ((array.Length > 0) && (arrayIndex >= array.Length))\r
- throw new ArgumentException ("arrayIndex is equal to or greater than array.Length");\r
-\r
- if (arrayIndex + items.Count > array.Length)\r
- throw new ArgumentException ("Not enough room from arrayIndex to end of array for this KeysCollection");\r
-#endif\r
-\r
- if (array != null && array.Rank > 1)\r
- throw new ArgumentException("array is multidimensional");\r
-\r
- object[] objArray = (object[])array;\r
- for (int i = 0; i < items.Count; i++, arrayIndex++)\r
- objArray[arrayIndex] = ((_Item)items[i]).key;\r
- }\r
-\r
- bool ICollection.IsSynchronized\r
- {\r
- get\r
- {\r
- return false;\r
- }\r
- }\r
- object ICollection.SyncRoot\r
- {\r
- get\r
- {\r
- return m_collection;\r
- }\r
- }\r
- /// <summary>\r
- /// Gets the number of keys in the NameObjectCollectionBase.KeysCollection\r
- /// </summary>\r
- public int Count\r
- {\r
- get\r
- {\r
- return m_collection.Count;\r
- }\r
- }\r
-\r
- public string this[int index]\r
- {\r
- get { return Get(index); }\r
- }\r
-\r
- // IEnumerable methods --------------------------------\r
- /// <summary>\r
- /// SDK: Returns an enumerator that can iterate through the NameObjectCollectionBase.KeysCollection.\r
- /// </summary>\r
- /// <returns></returns>\r
- public IEnumerator GetEnumerator()\r
- {\r
- return new _KeysEnumerator(m_collection);\r
- }\r
- }\r
-\r
- //--------------- Protected Instance Constructors --------------\r
-\r
- /// <summary>\r
- /// SDK: Initializes a new instance of the NameObjectCollectionBase class that is empty.\r
- /// </summary>\r
- protected NameObjectCollectionBase()\r
- {\r
- m_readonly = false;\r
-#if NET_1_0\r
- m_hashprovider = CaseInsensitiveHashCodeProvider.Default;\r
- m_comparer = CaseInsensitiveComparer.Default;\r
-#else\r
- m_hashprovider = CaseInsensitiveHashCodeProvider.DefaultInvariant;\r
- m_comparer = CaseInsensitiveComparer.DefaultInvariant;\r
-#endif\r
- m_defCapacity = 0;\r
- Init();\r
- }\r
-\r
- protected NameObjectCollectionBase(int capacity)\r
- {\r
- m_readonly = false;\r
-#if NET_1_0\r
- m_hashprovider = CaseInsensitiveHashCodeProvider.Default;\r
- m_comparer = CaseInsensitiveComparer.Default;\r
-#else\r
- m_hashprovider = CaseInsensitiveHashCodeProvider.DefaultInvariant;\r
- m_comparer = CaseInsensitiveComparer.DefaultInvariant;\r
-#endif\r
- m_defCapacity = capacity;\r
- Init();\r
- }\r
-\r
-#if NET_2_0\r
-\r
- internal NameObjectCollectionBase (IEqualityComparer equalityComparer, IComparer comparer, IHashCodeProvider hcp)\r
- {\r
- equality_comparer = equalityComparer;\r
- m_comparer = comparer;\r
- m_hashprovider = hcp;\r
- m_readonly = false;\r
- m_defCapacity = 0;\r
- Init ();\r
- }\r
-\r
- protected NameObjectCollectionBase (IEqualityComparer equalityComparer) : this( (equalityComparer == null ? StringComparer.InvariantCultureIgnoreCase : equalityComparer), null, null)\r
- { \r
- } \r
-\r
- [Obsolete ("Use NameObjectCollectionBase(IEqualityComparer)")]\r
-#endif\r
- protected NameObjectCollectionBase(IHashCodeProvider hashProvider, IComparer comparer)\r
- {\r
- m_comparer = comparer;\r
- m_hashprovider = hashProvider;\r
- m_readonly = false;\r
- m_defCapacity = 0;\r
- Init();\r
- }\r
-\r
- protected NameObjectCollectionBase(SerializationInfo info, StreamingContext context)\r
- {\r
- infoCopy = info;\r
- }\r
-\r
-#if NET_2_0\r
- protected NameObjectCollectionBase (int capacity, IEqualityComparer equalityComparer)\r
- {\r
- m_readonly = false;\r
- equality_comparer = (equalityComparer == null ? StringComparer.InvariantCultureIgnoreCase : equalityComparer);\r
- m_defCapacity = capacity;\r
- Init();\r
- }\r
-\r
- [Obsolete ("Use NameObjectCollectionBase(int,IEqualityComparer)")]\r
-#endif\r
- protected NameObjectCollectionBase(int capacity, IHashCodeProvider hashProvider, IComparer comparer)\r
- {\r
- m_readonly = false;\r
-\r
- m_hashprovider = hashProvider;\r
- m_comparer = comparer;\r
- m_defCapacity = capacity;\r
- Init();\r
- }\r
-\r
- private void Init()\r
- {\r
-#if NET_2_0\r
- if (equality_comparer != null)\r
- m_ItemsContainer = new Hashtable (m_defCapacity, equality_comparer);\r
- else\r
- m_ItemsContainer = new Hashtable (m_defCapacity, m_hashprovider, m_comparer);\r
-#else\r
- m_ItemsContainer = new Hashtable(m_defCapacity, m_hashprovider, m_comparer);\r
-#endif\r
- m_ItemsArray = new ArrayList();\r
- m_NullKeyItem = null;\r
- }\r
-\r
- //--------------- Public Instance Properties -------------------\r
-\r
- public virtual NameObjectCollectionBase.KeysCollection Keys\r
- {\r
- get\r
- {\r
- if (keyscoll == null)\r
- keyscoll = new KeysCollection(this);\r
- return keyscoll;\r
- }\r
- }\r
-\r
- //--------------- Public Instance Methods ----------------------\r
- // \r
- /// <summary>\r
- /// SDK: Returns an enumerator that can iterate through the NameObjectCollectionBase.\r
- /// \r
- /// <remark>This enumerator returns the keys of the collection as strings.</remark>\r
- /// </summary>\r
- /// <returns></returns>\r
- public\r
-#if NET_2_0 \r
- virtual\r
-#endif\r
- IEnumerator GetEnumerator()\r
- {\r
- return new _KeysEnumerator(this);\r
- }\r
-\r
- // ISerializable\r
- public virtual void GetObjectData(SerializationInfo info, StreamingContext context)\r
- {\r
- if (info == null)\r
- throw new ArgumentNullException("info");\r
-\r
- int count = Count;\r
- string[] keys = new string[count];\r
- object[] values = new object[count];\r
- int i = 0;\r
- foreach (_Item item in m_ItemsArray)\r
- {\r
- keys[i] = item.key;\r
- values[i] = item.value;\r
- i++;\r
- }\r
-\r
-#if NET_2_0\r
- if (equality_comparer != null) {\r
- info.AddValue ("KeyComparer", equality_comparer, typeof (IEqualityComparer));\r
- info.AddValue ("Version", 4, typeof (int));\r
- } else {\r
- info.AddValue ("HashProvider", m_hashprovider, typeof (IHashCodeProvider));\r
- info.AddValue ("Comparer", m_comparer, typeof (IComparer));\r
- info.AddValue ("Version", 2, typeof (int));\r
- }\r
-#else\r
- info.AddValue("HashProvider", m_hashprovider, typeof(IHashCodeProvider));\r
- info.AddValue("Comparer", m_comparer, typeof(IComparer));\r
-#endif\r
- info.AddValue("ReadOnly", m_readonly);\r
- info.AddValue("Count", count);\r
- info.AddValue("Keys", keys, typeof(string[]));\r
- info.AddValue("Values", values, typeof(object[]));\r
- }\r
-\r
- // ICollection\r
- public virtual int Count\r
- {\r
- get\r
- {\r
- return m_ItemsArray.Count;\r
- }\r
- }\r
-\r
- bool ICollection.IsSynchronized\r
- {\r
- get { return false; }\r
- }\r
-\r
- object ICollection.SyncRoot\r
- {\r
- get { return this; }\r
- }\r
-\r
- void ICollection.CopyTo(Array array, int index)\r
- {\r
- ((ICollection)Keys).CopyTo(array, index);\r
- }\r
-\r
- // IDeserializationCallback\r
- public virtual void OnDeserialization(object sender)\r
- {\r
- SerializationInfo info = infoCopy;\r
-\r
- // If a subclass overrides the serialization constructor\r
- // and inplements its own serialization process, infoCopy will\r
- // be null and we can ignore this callback.\r
- if (info == null)\r
- return;\r
-\r
- infoCopy = null;\r
- m_hashprovider = (IHashCodeProvider)info.GetValue("HashProvider",\r
- typeof(IHashCodeProvider));\r
-#if NET_2_0\r
- if (m_hashprovider == null) {\r
- equality_comparer = (IEqualityComparer) info.GetValue ("KeyComparer", typeof (IEqualityComparer));\r
- } else {\r
- m_comparer = (IComparer) info.GetValue ("Comparer", typeof (IComparer));\r
- if (m_comparer == null)\r
- throw new SerializationException ("The comparer is null");\r
- }\r
-#else\r
- if (m_hashprovider == null)\r
- throw new SerializationException("The hash provider is null");\r
-\r
- m_comparer = (IComparer)info.GetValue("Comparer", typeof(IComparer));\r
- if (m_comparer == null)\r
- throw new SerializationException("The comparer is null");\r
-#endif\r
- m_readonly = info.GetBoolean("ReadOnly");\r
- string[] keys = (string[])info.GetValue("Keys", typeof(string[]));\r
- if (keys == null)\r
- throw new SerializationException("keys is null");\r
-\r
- object[] values = (object[])info.GetValue("Values", typeof(object[]));\r
- if (values == null)\r
- throw new SerializationException("values is null");\r
-\r
- Init();\r
- int count = keys.Length;\r
- for (int i = 0; i < count; i++)\r
- BaseAdd(keys[i], values[i]);\r
- }\r
-\r
- //--------------- Protected Instance Properties ----------------\r
- /// <summary>\r
- /// SDK: Gets or sets a value indicating whether the NameObjectCollectionBase instance is read-only.\r
- /// </summary>\r
- protected bool IsReadOnly\r
- {\r
- get\r
- {\r
- return m_readonly;\r
- }\r
- set\r
- {\r
- m_readonly = value;\r
- }\r
- }\r
-\r
- //--------------- Protected Instance Methods -------------------\r
- /// <summary>\r
- /// Adds an Item with the specified key and value into the <see cref="NameObjectCollectionBase"/>NameObjectCollectionBase instance.\r
- /// </summary>\r
- /// <param name="name"></param>\r
- /// <param name="value"></param>\r
- protected void BaseAdd(string name, object value)\r
- {\r
- if (this.IsReadOnly)\r
- throw new NotSupportedException("Collection is read-only");\r
-\r
- _Item newitem = new _Item(name, value);\r
-\r
- if (name == null)\r
- {\r
- //todo: consider nullkey entry\r
- if (m_NullKeyItem == null)\r
- m_NullKeyItem = newitem;\r
- }\r
- else\r
- if (m_ItemsContainer[name] == null)\r
- {\r
- m_ItemsContainer.Add(name, newitem);\r
- }\r
- m_ItemsArray.Add(newitem);\r
- }\r
-\r
- protected void BaseClear()\r
- {\r
- if (this.IsReadOnly)\r
- throw new NotSupportedException("Collection is read-only");\r
- Init();\r
- }\r
-\r
- /// <summary>\r
- /// SDK: Gets the value of the entry at the specified index of the NameObjectCollectionBase instance.\r
- /// </summary>\r
- /// <param name="index"></param>\r
- /// <returns></returns>\r
- protected object BaseGet(int index)\r
- {\r
- return ((_Item)m_ItemsArray[index]).value;\r
- }\r
-\r
- /// <summary>\r
- /// SDK: Gets the value of the first entry with the specified key from the NameObjectCollectionBase instance.\r
- /// </summary>\r
- /// <remark>CAUTION: The BaseGet method does not distinguish between a null reference which is returned because the specified key is not found and a null reference which is returned because the value associated with the key is a null reference.</remark>\r
- /// <param name="name"></param>\r
- /// <returns></returns>\r
- protected object BaseGet(string name)\r
- {\r
- _Item item = FindFirstMatchedItem(name);\r
- /// CAUTION: The BaseGet method does not distinguish between a null reference which is returned because the specified key is not found and a null reference which is returned because the value associated with the key is a null reference.\r
- if (item == null)\r
- return null;\r
- else\r
- return item.value;\r
- }\r
-\r
- /// <summary>\r
- /// SDK:Returns a String array that contains all the keys in the NameObjectCollectionBase instance.\r
- /// </summary>\r
- /// <returns>A String array that contains all the keys in the NameObjectCollectionBase instance.</returns>\r
- protected string[] BaseGetAllKeys()\r
- {\r
- int cnt = m_ItemsArray.Count;\r
- string[] allKeys = new string[cnt];\r
- for (int i = 0; i < cnt; i++)\r
- allKeys[i] = BaseGetKey(i);//((_Item)m_ItemsArray[i]).key;\r
-\r
- return allKeys;\r
- }\r
-\r
- /// <summary>\r
- /// SDK: Returns an Object array that contains all the values in the NameObjectCollectionBase instance.\r
- /// </summary>\r
- /// <returns>An Object array that contains all the values in the NameObjectCollectionBase instance.</returns>\r
- protected object[] BaseGetAllValues()\r
- {\r
- int cnt = m_ItemsArray.Count;\r
- object[] allValues = new object[cnt];\r
- for (int i = 0; i < cnt; i++)\r
- allValues[i] = BaseGet(i);\r
-\r
- return allValues;\r
- }\r
-\r
- protected object[] BaseGetAllValues(Type type)\r
- {\r
- if (type == null)\r
- throw new ArgumentNullException("'type' argument can't be null");\r
- int cnt = m_ItemsArray.Count;\r
- object[] allValues = (object[])Array.CreateInstance(type, cnt);\r
- for (int i = 0; i < cnt; i++)\r
- allValues[i] = BaseGet(i);\r
-\r
- return allValues;\r
- }\r
-\r
- protected string BaseGetKey(int index)\r
- {\r
- return ((_Item)m_ItemsArray[index]).key;\r
- }\r
-\r
- /// <summary>\r
- /// Gets a value indicating whether the NameObjectCollectionBase instance contains entries whose keys are not a null reference \r
- /// </summary>\r
- /// <returns>true if the NameObjectCollectionBase instance contains entries whose keys are not a null reference otherwise, false.</returns>\r
- protected bool BaseHasKeys()\r
- {\r
- return (m_ItemsContainer.Count > 0);\r
- }\r
-\r
- protected void BaseRemove(string name)\r
- {\r
- int cnt = 0;\r
- String key;\r
- if (this.IsReadOnly)\r
- throw new NotSupportedException("Collection is read-only");\r
- if (name != null)\r
- {\r
- m_ItemsContainer.Remove(name);\r
- }\r
- else\r
- {\r
- m_NullKeyItem = null;\r
- }\r
-\r
- cnt = m_ItemsArray.Count;\r
- for (int i = 0; i < cnt; )\r
- {\r
- key = BaseGetKey(i);\r
- if (Equals(key, name))\r
- {\r
- m_ItemsArray.RemoveAt(i);\r
- cnt--;\r
- }\r
- else\r
- i++;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// \r
- /// </summary>\r
- /// <param name="index"></param>\r
- /// <LAME>This function implemented the way Microsoft implemented it - \r
- /// item is removed from hashtable and array without considering the case when there are two items with the same key but different values in array.\r
- /// E.g. if\r
- /// hashtable is [("Key1","value1")] and array contains [("Key1","value1")("Key1","value2")] then\r
- /// after RemoveAt(1) the collection will be in following state:\r
- /// hashtable:[] \r
- /// array: [("Key1","value1")] \r
- /// It's ok only then the key is uniquely assosiated with the value\r
- /// To fix it a comparsion of objects stored under the same key in the hashtable and in the arraylist should be added \r
- /// </LAME>>\r
- protected void BaseRemoveAt(int index)\r
- {\r
- if (this.IsReadOnly)\r
- throw new NotSupportedException("Collection is read-only");\r
- string key = BaseGetKey(index);\r
- if (key != null)\r
- {\r
- // TODO: see LAME description above\r
- m_ItemsContainer.Remove(key);\r
- }\r
- else\r
- m_NullKeyItem = null;\r
- m_ItemsArray.RemoveAt(index);\r
- }\r
-\r
- /// <summary>\r
- /// SDK: Sets the value of the entry at the specified index of the NameObjectCollectionBase instance.\r
- /// </summary>\r
- /// <param name="index"></param>\r
- /// <param name="value"></param>\r
- protected void BaseSet(int index, object value)\r
- {\r
-#if NET_2_0\r
- if (this.IsReadOnly)\r
- throw new NotSupportedException("Collection is read-only");\r
-#endif\r
- _Item item = (_Item)m_ItemsArray[index];\r
- item.value = value;\r
- }\r
-\r
- /// <summary>\r
- /// Sets the value of the first entry with the specified key in the NameObjectCollectionBase instance, if found; otherwise, adds an entry with the specified key and value into the NameObjectCollectionBase instance.\r
- /// </summary>\r
- /// <param name="name">The String key of the entry to set. The key can be a null reference </param>\r
- /// <param name="value">The Object that represents the new value of the entry to set. The value can be a null reference</param>\r
- protected void BaseSet(string name, object value)\r
- {\r
-#if NET_2_0\r
- if (this.IsReadOnly)\r
- throw new NotSupportedException("Collection is read-only");\r
-#endif\r
- _Item item = FindFirstMatchedItem(name);\r
- if (item != null)\r
- item.value = value;\r
- else\r
- BaseAdd(name, value);\r
- }\r
-\r
- private _Item FindFirstMatchedItem(string name)\r
- {\r
- if (name != null)\r
- return (_Item)m_ItemsContainer[name];\r
- else\r
- {\r
- //TODO: consider null key case\r
- return m_NullKeyItem;\r
- }\r
- }\r
-\r
- internal bool Equals(string s1, string s2)\r
- {\r
-#if NET_2_0\r
- if (m_comparer != null)\r
- return (m_comparer.Compare (s1, s2) == 0);\r
- else\r
- return equality_comparer.Equals (s1, s2);\r
-#else\r
- return (m_comparer.Compare(s1, s2) == 0);\r
-#endif\r
- }\r
- }\r
-}\r
-#endif\r
+using System;
+using System.Collections;
+using System.Runtime.Serialization;
+
+#if NO_SYSTEM_DLL
+namespace System.Collections.Specialized
+{
+ [Serializable]
+ public abstract class NameObjectCollectionBase : ICollection, IEnumerable, ISerializable, IDeserializationCallback
+ {
+ private Hashtable m_ItemsContainer;
+ /// <summary>
+ /// Extends Hashtable based Items container to support storing null-key pairs
+ /// </summary>
+ private _Item m_NullKeyItem;
+ private ArrayList m_ItemsArray;
+ private IHashCodeProvider m_hashprovider;
+ private IComparer m_comparer;
+ private int m_defCapacity;
+ private bool m_readonly;
+ SerializationInfo infoCopy;
+ private KeysCollection keyscoll;
+#if NET_2_0
+ private IEqualityComparer equality_comparer;
+
+ internal IEqualityComparer EqualityComparer {
+ get { return equality_comparer; }
+ }
+#endif
+ internal IComparer Comparer
+ {
+ get { return m_comparer; }
+ }
+
+ internal IHashCodeProvider HashCodeProvider
+ {
+ get { return m_hashprovider; }
+ }
+
+ internal class _Item
+ {
+ public string key;
+ public object value;
+ public _Item(string key, object value)
+ {
+ this.key = key;
+ this.value = value;
+ }
+ }
+ /// <summary>
+ /// Implements IEnumerable interface for KeysCollection
+ /// </summary>
+ [Serializable]
+ internal class _KeysEnumerator : IEnumerator
+ {
+ private NameObjectCollectionBase m_collection;
+ private int m_position;
+
+ internal _KeysEnumerator(NameObjectCollectionBase collection)
+ {
+ m_collection = collection;
+ Reset();
+ }
+ public object Current
+ {
+
+ get
+ {
+ if ((m_position < m_collection.Count) || (m_position < 0))
+ return m_collection.BaseGetKey(m_position);
+ else
+ throw new InvalidOperationException();
+ }
+
+ }
+ public bool MoveNext()
+ {
+ return ((++m_position) < m_collection.Count);
+ }
+ public void Reset()
+ {
+ m_position = -1;
+ }
+ }
+
+ /// <summary>
+ /// SDK: Represents a collection of the String keys of a collection.
+ /// </summary>
+ [Serializable]
+ public class KeysCollection : ICollection, IEnumerable
+ {
+ private NameObjectCollectionBase m_collection;
+
+ internal KeysCollection(NameObjectCollectionBase collection)
+ {
+ this.m_collection = collection;
+ }
+
+ public virtual string Get(int index)
+ {
+ return m_collection.BaseGetKey(index);
+ }
+
+ // ICollection methods -----------------------------------
+ void ICollection.CopyTo(Array array, int arrayIndex)
+ {
+ ArrayList items = m_collection.m_ItemsArray;
+#if NET_2_0
+ if (null == array)
+ throw new ArgumentNullException ("array");
+
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException ("arrayIndex");
+
+ if ((array.Length > 0) && (arrayIndex >= array.Length))
+ throw new ArgumentException ("arrayIndex is equal to or greater than array.Length");
+
+ if (arrayIndex + items.Count > array.Length)
+ throw new ArgumentException ("Not enough room from arrayIndex to end of array for this KeysCollection");
+#endif
+
+ if (array != null && array.Rank > 1)
+ throw new ArgumentException("array is multidimensional");
+
+ object[] objArray = (object[])array;
+ for (int i = 0; i < items.Count; i++, arrayIndex++)
+ objArray[arrayIndex] = ((_Item)items[i]).key;
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get
+ {
+ return false;
+ }
+ }
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ return m_collection;
+ }
+ }
+ /// <summary>
+ /// Gets the number of keys in the NameObjectCollectionBase.KeysCollection
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ return m_collection.Count;
+ }
+ }
+
+ public string this[int index]
+ {
+ get { return Get(index); }
+ }
+
+ // IEnumerable methods --------------------------------
+ /// <summary>
+ /// SDK: Returns an enumerator that can iterate through the NameObjectCollectionBase.KeysCollection.
+ /// </summary>
+ /// <returns></returns>
+ public IEnumerator GetEnumerator()
+ {
+ return new _KeysEnumerator(m_collection);
+ }
+ }
+
+ //--------------- Protected Instance Constructors --------------
+
+ /// <summary>
+ /// SDK: Initializes a new instance of the NameObjectCollectionBase class that is empty.
+ /// </summary>
+ protected NameObjectCollectionBase()
+ {
+ m_readonly = false;
+#if NET_1_0
+ m_hashprovider = CaseInsensitiveHashCodeProvider.Default;
+ m_comparer = CaseInsensitiveComparer.Default;
+#else
+ m_hashprovider = CaseInsensitiveHashCodeProvider.DefaultInvariant;
+ m_comparer = CaseInsensitiveComparer.DefaultInvariant;
+#endif
+ m_defCapacity = 0;
+ Init();
+ }
+
+ protected NameObjectCollectionBase(int capacity)
+ {
+ m_readonly = false;
+#if NET_1_0
+ m_hashprovider = CaseInsensitiveHashCodeProvider.Default;
+ m_comparer = CaseInsensitiveComparer.Default;
+#else
+ m_hashprovider = CaseInsensitiveHashCodeProvider.DefaultInvariant;
+ m_comparer = CaseInsensitiveComparer.DefaultInvariant;
+#endif
+ m_defCapacity = capacity;
+ Init();
+ }
+
+#if NET_2_0
+
+ internal NameObjectCollectionBase (IEqualityComparer equalityComparer, IComparer comparer, IHashCodeProvider hcp)
+ {
+ equality_comparer = equalityComparer;
+ m_comparer = comparer;
+ m_hashprovider = hcp;
+ m_readonly = false;
+ m_defCapacity = 0;
+ Init ();
+ }
+
+ protected NameObjectCollectionBase (IEqualityComparer equalityComparer) : this( (equalityComparer == null ? StringComparer.InvariantCultureIgnoreCase : equalityComparer), null, null)
+ {
+ }
+
+ [Obsolete ("Use NameObjectCollectionBase(IEqualityComparer)")]
+#endif
+ protected NameObjectCollectionBase(IHashCodeProvider hashProvider, IComparer comparer)
+ {
+ m_comparer = comparer;
+ m_hashprovider = hashProvider;
+ m_readonly = false;
+ m_defCapacity = 0;
+ Init();
+ }
+
+ protected NameObjectCollectionBase(SerializationInfo info, StreamingContext context)
+ {
+ infoCopy = info;
+ }
+
+#if NET_2_0
+ protected NameObjectCollectionBase (int capacity, IEqualityComparer equalityComparer)
+ {
+ m_readonly = false;
+ equality_comparer = (equalityComparer == null ? StringComparer.InvariantCultureIgnoreCase : equalityComparer);
+ m_defCapacity = capacity;
+ Init();
+ }
+
+ [Obsolete ("Use NameObjectCollectionBase(int,IEqualityComparer)")]
+#endif
+ protected NameObjectCollectionBase(int capacity, IHashCodeProvider hashProvider, IComparer comparer)
+ {
+ m_readonly = false;
+
+ m_hashprovider = hashProvider;
+ m_comparer = comparer;
+ m_defCapacity = capacity;
+ Init();
+ }
+
+ private void Init()
+ {
+#if NET_2_0
+ if (equality_comparer != null)
+ m_ItemsContainer = new Hashtable (m_defCapacity, equality_comparer);
+ else
+ m_ItemsContainer = new Hashtable (m_defCapacity, m_hashprovider, m_comparer);
+#else
+ m_ItemsContainer = new Hashtable(m_defCapacity, m_hashprovider, m_comparer);
+#endif
+ m_ItemsArray = new ArrayList();
+ m_NullKeyItem = null;
+ }
+
+ //--------------- Public Instance Properties -------------------
+
+ public virtual NameObjectCollectionBase.KeysCollection Keys
+ {
+ get
+ {
+ if (keyscoll == null)
+ keyscoll = new KeysCollection(this);
+ return keyscoll;
+ }
+ }
+
+ //--------------- Public Instance Methods ----------------------
+ //
+ /// <summary>
+ /// SDK: Returns an enumerator that can iterate through the NameObjectCollectionBase.
+ ///
+ /// <remark>This enumerator returns the keys of the collection as strings.</remark>
+ /// </summary>
+ /// <returns></returns>
+ public
+#if NET_2_0
+ virtual
+#endif
+ IEnumerator GetEnumerator()
+ {
+ return new _KeysEnumerator(this);
+ }
+
+ // ISerializable
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+
+ int count = Count;
+ string[] keys = new string[count];
+ object[] values = new object[count];
+ int i = 0;
+ foreach (_Item item in m_ItemsArray)
+ {
+ keys[i] = item.key;
+ values[i] = item.value;
+ i++;
+ }
+
+#if NET_2_0
+ if (equality_comparer != null) {
+ info.AddValue ("KeyComparer", equality_comparer, typeof (IEqualityComparer));
+ info.AddValue ("Version", 4, typeof (int));
+ } else {
+ info.AddValue ("HashProvider", m_hashprovider, typeof (IHashCodeProvider));
+ info.AddValue ("Comparer", m_comparer, typeof (IComparer));
+ info.AddValue ("Version", 2, typeof (int));
+ }
+#else
+ info.AddValue("HashProvider", m_hashprovider, typeof(IHashCodeProvider));
+ info.AddValue("Comparer", m_comparer, typeof(IComparer));
+#endif
+ info.AddValue("ReadOnly", m_readonly);
+ info.AddValue("Count", count);
+ info.AddValue("Keys", keys, typeof(string[]));
+ info.AddValue("Values", values, typeof(object[]));
+ }
+
+ // ICollection
+ public virtual int Count
+ {
+ get
+ {
+ return m_ItemsArray.Count;
+ }
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot
+ {
+ get { return this; }
+ }
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ ((ICollection)Keys).CopyTo(array, index);
+ }
+
+ // IDeserializationCallback
+ public virtual void OnDeserialization(object sender)
+ {
+ SerializationInfo info = infoCopy;
+
+ // If a subclass overrides the serialization constructor
+ // and inplements its own serialization process, infoCopy will
+ // be null and we can ignore this callback.
+ if (info == null)
+ return;
+
+ infoCopy = null;
+ m_hashprovider = (IHashCodeProvider)info.GetValue("HashProvider",
+ typeof(IHashCodeProvider));
+#if NET_2_0
+ if (m_hashprovider == null) {
+ equality_comparer = (IEqualityComparer) info.GetValue ("KeyComparer", typeof (IEqualityComparer));
+ } else {
+ m_comparer = (IComparer) info.GetValue ("Comparer", typeof (IComparer));
+ if (m_comparer == null)
+ throw new SerializationException ("The comparer is null");
+ }
+#else
+ if (m_hashprovider == null)
+ throw new SerializationException("The hash provider is null");
+
+ m_comparer = (IComparer)info.GetValue("Comparer", typeof(IComparer));
+ if (m_comparer == null)
+ throw new SerializationException("The comparer is null");
+#endif
+ m_readonly = info.GetBoolean("ReadOnly");
+ string[] keys = (string[])info.GetValue("Keys", typeof(string[]));
+ if (keys == null)
+ throw new SerializationException("keys is null");
+
+ object[] values = (object[])info.GetValue("Values", typeof(object[]));
+ if (values == null)
+ throw new SerializationException("values is null");
+
+ Init();
+ int count = keys.Length;
+ for (int i = 0; i < count; i++)
+ BaseAdd(keys[i], values[i]);
+ }
+
+ //--------------- Protected Instance Properties ----------------
+ /// <summary>
+ /// SDK: Gets or sets a value indicating whether the NameObjectCollectionBase instance is read-only.
+ /// </summary>
+ protected bool IsReadOnly
+ {
+ get
+ {
+ return m_readonly;
+ }
+ set
+ {
+ m_readonly = value;
+ }
+ }
+
+ //--------------- Protected Instance Methods -------------------
+ /// <summary>
+ /// Adds an Item with the specified key and value into the <see cref="NameObjectCollectionBase"/>NameObjectCollectionBase instance.
+ /// </summary>
+ /// <param name="name"></param>
+ /// <param name="value"></param>
+ protected void BaseAdd(string name, object value)
+ {
+ if (this.IsReadOnly)
+ throw new NotSupportedException("Collection is read-only");
+
+ _Item newitem = new _Item(name, value);
+
+ if (name == null)
+ {
+ //todo: consider nullkey entry
+ if (m_NullKeyItem == null)
+ m_NullKeyItem = newitem;
+ }
+ else
+ if (m_ItemsContainer[name] == null)
+ {
+ m_ItemsContainer.Add(name, newitem);
+ }
+ m_ItemsArray.Add(newitem);
+ }
+
+ protected void BaseClear()
+ {
+ if (this.IsReadOnly)
+ throw new NotSupportedException("Collection is read-only");
+ Init();
+ }
+
+ /// <summary>
+ /// SDK: Gets the value of the entry at the specified index of the NameObjectCollectionBase instance.
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ protected object BaseGet(int index)
+ {
+ return ((_Item)m_ItemsArray[index]).value;
+ }
+
+ /// <summary>
+ /// SDK: Gets the value of the first entry with the specified key from the NameObjectCollectionBase instance.
+ /// </summary>
+ /// <remark>CAUTION: The BaseGet method does not distinguish between a null reference which is returned because the specified key is not found and a null reference which is returned because the value associated with the key is a null reference.</remark>
+ /// <param name="name"></param>
+ /// <returns></returns>
+ protected object BaseGet(string name)
+ {
+ _Item item = FindFirstMatchedItem(name);
+ /// CAUTION: The BaseGet method does not distinguish between a null reference which is returned because the specified key is not found and a null reference which is returned because the value associated with the key is a null reference.
+ if (item == null)
+ return null;
+ else
+ return item.value;
+ }
+
+ /// <summary>
+ /// SDK:Returns a String array that contains all the keys in the NameObjectCollectionBase instance.
+ /// </summary>
+ /// <returns>A String array that contains all the keys in the NameObjectCollectionBase instance.</returns>
+ protected string[] BaseGetAllKeys()
+ {
+ int cnt = m_ItemsArray.Count;
+ string[] allKeys = new string[cnt];
+ for (int i = 0; i < cnt; i++)
+ allKeys[i] = BaseGetKey(i);//((_Item)m_ItemsArray[i]).key;
+
+ return allKeys;
+ }
+
+ /// <summary>
+ /// SDK: Returns an Object array that contains all the values in the NameObjectCollectionBase instance.
+ /// </summary>
+ /// <returns>An Object array that contains all the values in the NameObjectCollectionBase instance.</returns>
+ protected object[] BaseGetAllValues()
+ {
+ int cnt = m_ItemsArray.Count;
+ object[] allValues = new object[cnt];
+ for (int i = 0; i < cnt; i++)
+ allValues[i] = BaseGet(i);
+
+ return allValues;
+ }
+
+ protected object[] BaseGetAllValues(Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException("'type' argument can't be null");
+ int cnt = m_ItemsArray.Count;
+ object[] allValues = (object[])Array.CreateInstance(type, cnt);
+ for (int i = 0; i < cnt; i++)
+ allValues[i] = BaseGet(i);
+
+ return allValues;
+ }
+
+ protected string BaseGetKey(int index)
+ {
+ return ((_Item)m_ItemsArray[index]).key;
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the NameObjectCollectionBase instance contains entries whose keys are not a null reference
+ /// </summary>
+ /// <returns>true if the NameObjectCollectionBase instance contains entries whose keys are not a null reference otherwise, false.</returns>
+ protected bool BaseHasKeys()
+ {
+ return (m_ItemsContainer.Count > 0);
+ }
+
+ protected void BaseRemove(string name)
+ {
+ int cnt = 0;
+ String key;
+ if (this.IsReadOnly)
+ throw new NotSupportedException("Collection is read-only");
+ if (name != null)
+ {
+ m_ItemsContainer.Remove(name);
+ }
+ else
+ {
+ m_NullKeyItem = null;
+ }
+
+ cnt = m_ItemsArray.Count;
+ for (int i = 0; i < cnt; )
+ {
+ key = BaseGetKey(i);
+ if (Equals(key, name))
+ {
+ m_ItemsArray.RemoveAt(i);
+ cnt--;
+ }
+ else
+ i++;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="index"></param>
+ /// <LAME>This function implemented the way Microsoft implemented it -
+ /// item is removed from hashtable and array without considering the case when there are two items with the same key but different values in array.
+ /// E.g. if
+ /// hashtable is [("Key1","value1")] and array contains [("Key1","value1")("Key1","value2")] then
+ /// after RemoveAt(1) the collection will be in following state:
+ /// hashtable:[]
+ /// array: [("Key1","value1")]
+ /// It's ok only then the key is uniquely assosiated with the value
+ /// To fix it a comparsion of objects stored under the same key in the hashtable and in the arraylist should be added
+ /// </LAME>>
+ protected void BaseRemoveAt(int index)
+ {
+ if (this.IsReadOnly)
+ throw new NotSupportedException("Collection is read-only");
+ string key = BaseGetKey(index);
+ if (key != null)
+ {
+ // TODO: see LAME description above
+ m_ItemsContainer.Remove(key);
+ }
+ else
+ m_NullKeyItem = null;
+ m_ItemsArray.RemoveAt(index);
+ }
+
+ /// <summary>
+ /// SDK: Sets the value of the entry at the specified index of the NameObjectCollectionBase instance.
+ /// </summary>
+ /// <param name="index"></param>
+ /// <param name="value"></param>
+ protected void BaseSet(int index, object value)
+ {
+#if NET_2_0
+ if (this.IsReadOnly)
+ throw new NotSupportedException("Collection is read-only");
+#endif
+ _Item item = (_Item)m_ItemsArray[index];
+ item.value = value;
+ }
+
+ /// <summary>
+ /// Sets the value of the first entry with the specified key in the NameObjectCollectionBase instance, if found; otherwise, adds an entry with the specified key and value into the NameObjectCollectionBase instance.
+ /// </summary>
+ /// <param name="name">The String key of the entry to set. The key can be a null reference </param>
+ /// <param name="value">The Object that represents the new value of the entry to set. The value can be a null reference</param>
+ protected void BaseSet(string name, object value)
+ {
+#if NET_2_0
+ if (this.IsReadOnly)
+ throw new NotSupportedException("Collection is read-only");
+#endif
+ _Item item = FindFirstMatchedItem(name);
+ if (item != null)
+ item.value = value;
+ else
+ BaseAdd(name, value);
+ }
+
+ private _Item FindFirstMatchedItem(string name)
+ {
+ if (name != null)
+ return (_Item)m_ItemsContainer[name];
+ else
+ {
+ //TODO: consider null key case
+ return m_NullKeyItem;
+ }
+ }
+
+ internal bool Equals(string s1, string s2)
+ {
+#if NET_2_0
+ if (m_comparer != null)
+ return (m_comparer.Compare (s1, s2) == 0);
+ else
+ return equality_comparer.Equals (s1, s2);
+#else
+ return (m_comparer.Compare(s1, s2) == 0);
+#endif
+ }
+ }
+}
+#endif