NameObjectCollectionBase.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / CompMod / System / Collections / Specialized / NameObjectCollectionBase.cs / 1305376 / NameObjectCollectionBase.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 * Ordered String/Object collection of name/value pairs with support for null key 
 *
 * This class is intended to be used as a base class 
 *
 * Copyright (c) 2000 Microsoft Corporation
 */
 
namespace System.Collections.Specialized {
 
    using Microsoft.Win32; 
    using System.Collections;
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization;
    using System.Runtime.Serialization;
    using System.Security.Permissions;
 

    ///  
    /// Provides the base class for a sorted collection of associated  keys 
    ///    and  values that can be accessed either with the hash code of
    ///    the key or with the index. 
    /// 
    [Serializable()]
    public abstract class NameObjectCollectionBase : ICollection, ISerializable, IDeserializationCallback {
        // const names used for serialization 
        private const String ReadOnlyName = "ReadOnly";
        private const String CountName = "Count"; 
        private const String ComparerName = "Comparer"; 
        private const String HashCodeProviderName = "HashProvider";
        private const String KeysName = "Keys"; 
        private const String ValuesName = "Values";
        private const String KeyComparerName = "KeyComparer";
        private const String VersionName = "Version";
 
        private bool _readOnly = false;
        private ArrayList _entriesArray; 
        private IEqualityComparer _keyComparer; 
        private Hashtable _entriesTable;
        private NameObjectEntry _nullKeyEntry; 
        private KeysCollection _keys;
        private SerializationInfo _serializationInfo;
        private int _version;
        [NonSerialized] 
        private Object _syncRoot;
 
        private static StringComparer defaultComparer = StringComparer.InvariantCultureIgnoreCase; 

        ///  
        ///  Creates an empty  instance with the default initial capacity and using the default case-insensitive hash
        ///    code provider and the default case-insensitive comparer.
        /// 
        protected NameObjectCollectionBase() :this(defaultComparer) { 
        }
 
        protected NameObjectCollectionBase(IEqualityComparer equalityComparer) 
        {
           _keyComparer = (equalityComparer == null) ? defaultComparer : equalityComparer; 
           Reset();
        }

        protected NameObjectCollectionBase(Int32 capacity, IEqualityComparer equalityComparer) : this (equalityComparer) 
        {
            Reset(capacity); 
        } 

 
        /// 
        /// Creates an empty  instance with
        ///    the default initial capacity and using the specified case-insensitive hash code provider and the
        ///    specified case-insensitive comparer. 
        /// 
 
#pragma warning disable 618 
        [Obsolete("Please use NameObjectCollectionBase(IEqualityComparer) instead.")]
        protected NameObjectCollectionBase(IHashCodeProvider hashProvider, IComparer comparer) { 
            _keyComparer = new CompatibleComparer( comparer, hashProvider);
            Reset();
        }
#pragma warning restore 618 

        ///  
        /// Creates an empty  instance with the specified 
        ///    initial capacity and using the specified case-insensitive hash code provider
        ///    and the specified case-insensitive comparer. 
        /// 
#pragma warning disable 618
        [Obsolete("Please use NameObjectCollectionBase(Int32, IEqualityComparer) instead.")]
        protected NameObjectCollectionBase(int capacity, IHashCodeProvider hashProvider, IComparer comparer) { 
            _keyComparer = new CompatibleComparer( comparer, hashProvider);
            Reset(capacity); 
        } 
#pragma warning restore 618
 
        /// 
        /// Creates an empty  instance with the specified
        ///    initial capacity and using the default case-insensitive hash code provider
        ///    and the default case-insensitive comparer. 
        /// 
        protected NameObjectCollectionBase(int capacity) { 
            _keyComparer = StringComparer.InvariantCultureIgnoreCase; 
            Reset(capacity);
        } 

        // Allow internal extenders to avoid creating the hashtable/arraylist.
        internal NameObjectCollectionBase(DBNull dummy)
        { 
        }
 
        // 
        // Serialization support
        // 

        /// 
        ///    [To be supplied.]
        ///  
        protected NameObjectCollectionBase(SerializationInfo info, StreamingContext context) {
            _serializationInfo = info; 
        } 

        ///  
        ///    [To be supplied.]
        /// 
        [SuppressMessage("Microsoft.Security", "CA2123:OverrideLinkDemandsShouldBeIdenticalToBase", Justification = "System.dll is still using pre-v4 security model and needs this demand")]
        [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)] 		 
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
            if (info == null) 
                throw new ArgumentNullException("info"); 

            info.AddValue(ReadOnlyName, _readOnly); 

#pragma warning disable 618
            // Maintain backward serialization compatibility if new APIs are not used.
            if( _keyComparer == defaultComparer) { 
                info.AddValue(HashCodeProviderName, CompatibleComparer.DefaultHashCodeProvider, typeof(IHashCodeProvider));
                info.AddValue(ComparerName, CompatibleComparer.DefaultComparer, typeof(IComparer)); 
            } 
            else if(_keyComparer == null) {
                info.AddValue(HashCodeProviderName, null, typeof(IHashCodeProvider)); 
                info.AddValue(ComparerName, null, typeof(IComparer));
            }
            else if(_keyComparer is CompatibleComparer) {
                CompatibleComparer c = (CompatibleComparer)_keyComparer; 
                info.AddValue(HashCodeProviderName, c.HashCodeProvider, typeof(IHashCodeProvider));
                info.AddValue(ComparerName, c.Comparer, typeof(IComparer)); 
            } 
            else {
                info.AddValue(KeyComparerName, _keyComparer, typeof(IEqualityComparer)); 
            }
#pragma warning restore 618

            int count = _entriesArray.Count; 
            info.AddValue(CountName, count);
 
            String[] keys = new String[count]; 
            Object[] values = new Object[count];
 
            for (int i = 0; i < count; i++) {
                NameObjectEntry entry = (NameObjectEntry)_entriesArray[i];
                keys[i] = entry.Key;
                values[i] = entry.Value; 
            }
 
            info.AddValue(KeysName, keys, typeof(String[])); 
            info.AddValue(ValuesName, values, typeof(Object[]));
            info.AddValue(VersionName, _version); 
        }

        /// 
        ///    [To be supplied.] 
        /// 
        public virtual void OnDeserialization(Object sender) { 
            if (_keyComparer != null) { 
                return;//Somebody had a dependency on this hashtable and fixed us up before the ObjectManager got to it.
            } 

            if (_serializationInfo == null)
                throw new SerializationException();
 
            SerializationInfo info = _serializationInfo;
            _serializationInfo = null; 
 
            bool readOnly = false;
            int count = 0; 
            String[] keys = null;
            Object[] values = null;
#pragma warning disable 618
            IHashCodeProvider hashProvider = null; 
#pragma warning restore 618
            IComparer comparer = null; 
            bool hasVersion = false; 
            int serializedVersion = 0;
 
            SerializationInfoEnumerator enumerator = info.GetEnumerator();
            while( enumerator.MoveNext())
            {
                switch( enumerator.Name) 
                {
                    case ReadOnlyName: 
                        readOnly = info.GetBoolean(ReadOnlyName);; 
                        break;
                    case HashCodeProviderName: 
#pragma warning disable 618
                        hashProvider = (IHashCodeProvider)info.GetValue(HashCodeProviderName, typeof(IHashCodeProvider));;
#pragma warning restore 618
                        break; 
                    case ComparerName:
                        comparer = (IComparer)info.GetValue(ComparerName, typeof(IComparer)); 
                        break; 
                    case KeyComparerName:
                        _keyComparer = (IEqualityComparer)info.GetValue(KeyComparerName, typeof(IEqualityComparer)); 
                        break;
                    case CountName:
                        count = info.GetInt32(CountName);
                        break; 
                    case KeysName:
                        keys = (String[])info.GetValue(KeysName, typeof(String[])); 
                        break; 
                    case ValuesName:
                        values = (Object[])info.GetValue(ValuesName, typeof(Object[])); 
                        break;
                    case VersionName:
                        hasVersion = true;
                        serializedVersion = info.GetInt32(VersionName); 
                        break;
                } 
            } 

            if( _keyComparer == null) { 
                if(comparer == null || hashProvider == null)
                {
                    throw new SerializationException();
                } 
                else {
                    // create a new key comparer for V1 Object 
                    _keyComparer = new CompatibleComparer(comparer, hashProvider); 
                }
            } 

            if ( keys == null || values == null)
                throw new SerializationException();
 
            Reset(count);
 
            for (int i = 0; i < count; i++) 
                BaseAdd(keys[i], values[i]);
 
            _readOnly = readOnly;  // after collection populated
            if(hasVersion) {
                _version = serializedVersion;
            } 
        }
 
        // 
        // Private helpers
        // 

        private void Reset() {
            _entriesArray = new ArrayList();
            _entriesTable = new Hashtable(_keyComparer); 
            _nullKeyEntry = null;
            _version++; 
        } 

        private void Reset(int capacity) { 
            _entriesArray = new ArrayList(capacity);
            _entriesTable = new Hashtable(capacity, _keyComparer);
            _nullKeyEntry = null;
            _version++; 
        }
 
        private NameObjectEntry FindEntry(String key) { 
            if (key != null)
                return (NameObjectEntry)_entriesTable[key]; 
            else
                return _nullKeyEntry;
        }
 
        internal IEqualityComparer Comparer
        { 
            get 
            {
                return _keyComparer; 
            }
            set
            {
                _keyComparer = value; 
            }
 
        } 

 
        /// 
        /// Gets or sets a value indicating whether the  instance is read-only.
        /// 
        protected bool IsReadOnly { 
            get { return _readOnly; }
            set { _readOnly = value; } 
        } 

        ///  
        /// Gets a value indicating whether the  instance contains entries whose
        ///    keys are not .
        /// 
        protected bool BaseHasKeys() { 
            return (_entriesTable.Count > 0);  // any entries with keys?
        } 
 
        //
        // Methods to add / remove entries 
        //

        /// 
        ///    Adds an entry with the specified key and value into the 
        ///     instance.
        ///  
        protected void BaseAdd(String name, Object value) { 
            if (_readOnly)
                throw new NotSupportedException(SR.GetString(SR.CollectionReadOnly)); 

            NameObjectEntry entry = new NameObjectEntry(name, value);

            // insert entry into hashtable 
            if (name != null) {
                if (_entriesTable[name] == null) 
                    _entriesTable.Add(name, entry); 
            }
            else { // null key -- special case -- hashtable doesn't like null keys 
                if (_nullKeyEntry == null)
                    _nullKeyEntry = entry;
            }
 
            // add entry to the list
            _entriesArray.Add(entry); 
 
            _version++;
        } 

        /// 
        ///    Removes the entries with the specified key from the
        ///     instance. 
        /// 
        protected void BaseRemove(String name) { 
            if (_readOnly) 
                throw new NotSupportedException(SR.GetString(SR.CollectionReadOnly));
 
            if (name != null) {
                // remove from hashtable
                _entriesTable.Remove(name);
 
                // remove from array
                for (int i = _entriesArray.Count-1; i >= 0; i--) { 
                    if (_keyComparer.Equals(name, BaseGetKey(i))) 
                        _entriesArray.RemoveAt(i);
                } 
            }
            else { // null key -- special case
                // null out special 'null key' entry
                _nullKeyEntry = null; 

                // remove from array 
                for (int i = _entriesArray.Count-1; i >= 0; i--) { 
                    if (BaseGetKey(i) == null)
                        _entriesArray.RemoveAt(i); 
                }
            }

            _version++; 
        }
 
        ///  
        ///     Removes the entry at the specified index of the
        ///     instance. 
        /// 
        protected void BaseRemoveAt(int index) {
            if (_readOnly)
                throw new NotSupportedException(SR.GetString(SR.CollectionReadOnly)); 

            String key = BaseGetKey(index); 
 
            if (key != null) {
                // remove from hashtable 
                _entriesTable.Remove(key);
            }
            else { // null key -- special case
                // null out special 'null key' entry 
                _nullKeyEntry = null;
            } 
 
            // remove from array
            _entriesArray.RemoveAt(index); 

            _version++;
        }
 
        /// 
        /// Removes all entries from the  instance. 
        ///  
        protected void BaseClear() {
            if (_readOnly) 
                throw new NotSupportedException(SR.GetString(SR.CollectionReadOnly));

            Reset();
        } 

        // 
        // Access by name 
        //
 
        /// 
        ///    Gets the value of the first entry with the specified key from
        ///       the  instance.
        ///  
        protected Object BaseGet(String name) {
            NameObjectEntry e = FindEntry(name); 
            return (e != null) ? e.Value : null; 
        }
 
        /// 
        /// Sets the value of the first entry with the specified key in the 
        /// instance, if found; otherwise, adds an entry with the specified key and value
        /// into the  
        /// instance.
        ///  
        protected void BaseSet(String name, Object value) { 
            if (_readOnly)
                throw new NotSupportedException(SR.GetString(SR.CollectionReadOnly)); 

            NameObjectEntry entry = FindEntry(name);
            if (entry != null) {
                entry.Value = value; 
                _version++;
            } 
            else { 
                BaseAdd(name, value);
            } 
        }

        //
        // Access by index 
        //
 
        ///  
        ///    Gets the value of the entry at the specified index of
        ///       the  instance. 
        /// 
        protected Object BaseGet(int index) {
            NameObjectEntry entry = (NameObjectEntry)_entriesArray[index];
            return entry.Value; 
        }
 
        ///  
        ///    Gets the key of the entry at the specified index of the
        ///     
        ///    instance.
        /// 
        protected String BaseGetKey(int index) {
            NameObjectEntry entry = (NameObjectEntry)_entriesArray[index]; 
            return entry.Key;
        } 
 
        /// 
        ///    Sets the value of the entry at the specified index of 
        ///       the  instance.
        /// 
        protected void BaseSet(int index, Object value) {
            if (_readOnly) 
                throw new NotSupportedException(SR.GetString(SR.CollectionReadOnly));
 
            NameObjectEntry entry = (NameObjectEntry)_entriesArray[index]; 
            entry.Value = value;
            _version++; 
        }

        //
        // ICollection implementation 
        //
 
        ///  
        /// Returns an enumerator that can iterate through the .
        ///  
        public virtual IEnumerator GetEnumerator() {
            return new NameObjectKeysEnumerator(this);
        }
 
        /// 
        /// Gets the number of key-and-value pairs in the  instance. 
        ///  
        public virtual int Count {
            get { 
                return _entriesArray.Count;
            }
        }
 
        void ICollection.CopyTo(Array array, int index) {
            if (array==null) { 
                throw new ArgumentNullException("array"); 
            }
 
            if (array.Rank != 1) {
                throw new ArgumentException(SR.GetString(SR.Arg_MultiRank));
            }
 
            if (index < 0) {
                throw new ArgumentOutOfRangeException("index",SR.GetString(SR.IndexOutOfRange, index.ToString(CultureInfo.CurrentCulture)) ); 
            } 

            if (array.Length - index < _entriesArray.Count) { 
                throw new ArgumentException(SR.GetString(SR.Arg_InsufficientSpace));
            }

            for (IEnumerator e = this.GetEnumerator(); e.MoveNext();) 
                array.SetValue(e.Current, index++);
        } 
 
        Object ICollection.SyncRoot {
            get { 
                if( _syncRoot == null) {
                    System.Threading.Interlocked.CompareExchange(ref _syncRoot, new Object(), null);
                }
                return _syncRoot; 
            }
        } 
 
        bool ICollection.IsSynchronized {
            get { return false; } 
        }

        //
        //  Helper methods to get arrays of keys and values 
        //
 
        ///  
        /// Returns a  array containing all the keys in the
        ///  instance. 
        /// 
        protected String[] BaseGetAllKeys() {
            int n = _entriesArray.Count;
            String[] allKeys = new String[n]; 

            for (int i = 0; i < n; i++) 
                allKeys[i] = BaseGetKey(i); 

            return allKeys; 
        }

        /// 
        /// Returns an  array containing all the values in the 
        ///  instance.
        ///  
        protected Object[] BaseGetAllValues() { 
            int n = _entriesArray.Count;
            Object[] allValues = new Object[n]; 

            for (int i = 0; i < n; i++)
                allValues[i] = BaseGet(i);
 
            return allValues;
        } 
 
        /// 
        ///    Returns an array of the specified type containing 
        ///       all the values in the  instance.
        /// 
        protected object[] BaseGetAllValues(Type type) {
            int n = _entriesArray.Count; 
            if (type == null) {
                throw new ArgumentNullException("type"); 
            } 
            object[] allValues = (object[]) SecurityUtils.ArrayCreateInstance(type, n);
 
            for (int i = 0; i < n; i++) {
                allValues[i] = BaseGet(i);
            }
 
            return allValues;
        } 
 
        //
        // Keys propetry 
        //

        /// 
        /// Returns a  instance containing 
        ///    all the keys in the  instance.
        ///  
        public virtual KeysCollection Keys { 
            get {
                if (_keys == null) 
                    _keys = new KeysCollection(this);
                return _keys;
            }
        } 

        // 
        // Simple entry class to allow substitution of values and indexed access to keys 
        //
 
        internal class NameObjectEntry {

            internal NameObjectEntry(String name, Object value) {
                Key = name; 
                Value = value;
            } 
 
            internal String Key;
            internal Object Value; 
        }

        //
        // Enumerator over keys of NameObjectCollection 
        //
 
        [Serializable()] 
        internal class NameObjectKeysEnumerator : IEnumerator {
            private int _pos; 
            private NameObjectCollectionBase _coll;
            private int _version;

            internal NameObjectKeysEnumerator(NameObjectCollectionBase coll) { 
                _coll = coll;
                _version = _coll._version; 
                _pos = -1; 
            }
 
            public bool MoveNext() {
                if ( _version != _coll._version)
                    throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_EnumFailedVersion));
 
                if( _pos < _coll.Count - 1) {
                    _pos++; 
                    return true; 
                }
                else { 
                    _pos = _coll.Count;
                    return false;
                }
 
            }
 
            public void Reset() { 
                if (_version != _coll._version)
                    throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_EnumFailedVersion)); 
                _pos = -1;
            }

            public Object Current { 
                get {
                    if(_pos >= 0 && _pos < _coll.Count) { 
                        return _coll.BaseGetKey(_pos); 
                    }
                    else { 
                        throw new InvalidOperationException(SR.GetString(SR.InvalidOperation_EnumOpCantHappen));
                    }
                }
            } 
        }
 
        // 
        // Keys collection
        // 

        /// 
        /// Represents a collection of the  keys of a collection.
        ///  
        [Serializable()]
        public class KeysCollection : ICollection { 
 
            private NameObjectCollectionBase _coll;
 
            internal KeysCollection(NameObjectCollectionBase coll) {
                _coll = coll;
            }
 
            // Indexed access
 
            ///  
            ///     Gets the key at the specified index of the collection.
            ///  
            public virtual String Get(int index) {
                return _coll.BaseGetKey(index);
            }
 
            /// 
            ///    Represents the entry at the specified index of the collection. 
            ///  
            public String this[int index] {
                get { 
                    return Get(index);
                }
            }
 
            // ICollection implementation
 
            ///  
            ///    Returns an enumerator that can iterate through the
            ///    . 
            /// 
            public IEnumerator GetEnumerator() {
                return new NameObjectKeysEnumerator(_coll);
            } 

            ///  
            /// Gets the number of keys in the . 
            /// 
            public int Count { 
                get {
                    return _coll.Count;
                }
            } 

            void ICollection.CopyTo(Array array, int index) { 
                if (array==null) { 
                    throw new ArgumentNullException("array");
                } 

                if (array.Rank != 1) {
                    throw new ArgumentException(SR.GetString(SR.Arg_MultiRank));
                } 

                if (index < 0) { 
                    throw new ArgumentOutOfRangeException("index",SR.GetString(SR.IndexOutOfRange, index.ToString(CultureInfo.CurrentCulture)) ); 
                }
 
                if (array.Length - index < _coll.Count) {
                    throw new ArgumentException(SR.GetString(SR.Arg_InsufficientSpace));
                }
 
                for (IEnumerator e = this.GetEnumerator(); e.MoveNext();)
                    array.SetValue(e.Current, index++); 
            } 

            Object ICollection.SyncRoot { 
                get { return ((ICollection)_coll).SyncRoot; }
            }

 
            bool ICollection.IsSynchronized {
                get { return false; } 
            } 
        }
    } 

    [Serializable()]
    internal class CompatibleComparer: IEqualityComparer  {
        IComparer _comparer; 
        static IComparer defaultComparer;
        // Needed for compatability 
#pragma warning disable 618 
        IHashCodeProvider _hcp;
 
        static IHashCodeProvider defaultHashProvider;

        internal CompatibleComparer(IComparer comparer, IHashCodeProvider hashCodeProvider) {
            _comparer = comparer; 
            _hcp = hashCodeProvider;
        } 
#pragma warning restore 618 

        public new bool Equals(Object a, Object b) { 
            if (a == b) return true;
            if (a == null || b == null) return false;

            // We must call Compare or CompareTo method 
            // to make sure everything is fine, but the
            // guideline is that Equals should never throw. 
            // So we need to ignore ArgumentException (note this 
            // is the exception we should get if two objects are not
            // comparable.) 

            try {
                if (_comparer != null)
                    return (_comparer.Compare(a,b) == 0); 

                IComparable ia = a as IComparable; 
                if (ia != null) 
                    return (ia.CompareTo(b) ==0);
            } 
            catch(ArgumentException) {
                return false;
            }
 
            return a.Equals(b);
        } 
 
        public int GetHashCode(Object obj) {
            if( obj == null) { 
                throw new ArgumentNullException("obj");
            }

            if (_hcp != null) 
                return _hcp.GetHashCode(obj);
            return obj.GetHashCode(); 
        } 

        public IComparer Comparer { 
            get {
                return _comparer;
            }
        } 

#pragma warning disable 618 
        public IHashCodeProvider HashCodeProvider { 
            get {
                return _hcp; 
            }
        }
#pragma warning restore 618
 
        public static IComparer DefaultComparer {
            get { 
                if( defaultComparer == null) { 
                    defaultComparer = new CaseInsensitiveComparer(CultureInfo.InvariantCulture);
                } 
                return defaultComparer;
            }
        }
 
#pragma warning disable 618
        public static IHashCodeProvider DefaultHashCodeProvider { 
            get { 
                if( defaultHashProvider == null) {
                    defaultHashProvider = new CaseInsensitiveHashCodeProvider(CultureInfo.InvariantCulture); 
                }
                return defaultHashProvider;
            }
        } 
#pragma warning restore 618
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK