ReadOnlyDictionaryBase.cs :  » Development » TULP2G » Wintellect » PowerCollections » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Development » TULP2G 
TULP2G » Wintellect » PowerCollections » ReadOnlyDictionaryBase.cs
//******************************
// Written by Peter Golde
// Copyright (c) 2004-2005, Wintellect
//
// Use and restribution of this code is subject to the license agreement 
// contained in the file "License.txt" accompanying this file.
//******************************

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;


namespace Wintellect.PowerCollections{
    /// <summary>
    /// ReadOnlyDictionaryBase is a base class that can be used to more easily implement the
    /// generic IDictionary&lt;T&gt; and non-generic IDictionary interfaces.
    /// </summary>
    /// <remarks>
    /// <para>To use ReadOnlyDictionaryBase as a base class, the derived class must override
    /// Count, TryGetValue, GetEnumerator. </para>
    /// </remarks>
    /// <typeparam name="TKey">The key type of the dictionary.</typeparam>
    /// <typeparam name="TValue">The value type of the dictionary.</typeparam>
    [Serializable]
    [DebuggerDisplay("{DebuggerDisplayString()}")]
    public abstract class ReadOnlyDictionaryBase<TKey, TValue> : ReadOnlyCollectionBase<KeyValuePair<TKey, TValue>>,
                                                                                                  IDictionary<TKey, TValue>, IDictionary
    {
        /// <summary>
        /// Creates a new DictionaryBase. This must be called from the constructor of the
        /// derived class to specify whether the dictionary is read-only and the name of the
        /// collection.
        /// </summary>
        protected ReadOnlyDictionaryBase()
        {
        }

        /// <summary>
        /// Throws an NotSupportedException stating that this collection cannot be modified.
        /// </summary>
        private void MethodModifiesCollection()
        {
            throw new NotSupportedException(string.Format(Strings.CannotModifyCollection, Util.SimpleClassName(this.GetType())));
        }

        /// <summary>
        /// Adds a new key-value pair to the dictionary. Always throws an exception
        /// indicating that this method is not supported in a read-only dictionary.
        /// </summary>
        /// <param name="key">Key to add.</param>
        /// <param name="value">Value to associated with the key.</param>
        /// <exception cref="NotSupportedException">Always thrown.</exception>
        void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
        {
            MethodModifiesCollection();
        }

        /// <summary>
        /// Removes a key from the dictionary. Always throws an exception
        /// indicating that this method is not supported in a read-only dictionary.
        /// </summary>
        /// <param name="key">Key to remove from the dictionary.</param>
        /// <returns>True if the key was found, false otherwise.</returns>
        /// <exception cref="NotSupportedException">Always thrown.</exception>
        public virtual bool Remove(TKey key)
        {
            MethodModifiesCollection();
            return false;
        }

        /// <summary>
        /// Determines whether a given key is found
        /// in the dictionary.
        /// </summary>
        /// <remarks>The default implementation simply calls TryGetValue and returns
        /// what it returns.</remarks>
        /// <param name="key">Key to look for in the dictionary.</param>
        /// <returns>True if the key is present in the dictionary.</returns>
        public virtual bool ContainsKey(TKey key)
        {
            TValue dummy;
            return TryGetValue(key, out dummy);
        }

        /// <summary>
        /// Determines if this dictionary contains a key equal to <paramref name="key"/>. If so, the value
        /// associated with that key is returned through the value parameter. This method must be overridden 
        /// in the derived class.
        /// </summary>
        /// <param name="key">The key to search for.</param>
        /// <param name="value">Returns the value associated with key, if true was returned.</param>
        /// <returns>True if the dictionary contains key. False if the dictionary does not contain key.</returns>
        public abstract bool TryGetValue(TKey key, out TValue value);

        /// <summary>
        /// The indexer of the dictionary. The set accessor throws an NotSupportedException
        /// stating the dictionary is read-only.
        /// </summary>
        /// <remarks>The get accessor is implemented by calling TryGetValue.</remarks>
        /// <param name="key">Key to find in the dictionary.</param>
        /// <returns>The value associated with the key.</returns>
        /// <exception cref="NotSupportedException">Always thrown from the set accessor, indicating
        /// that the dictionary is read only.</exception>
        /// <exception cref="KeyNotFoundException">Thrown from the get accessor if the key
        /// was not found.</exception>
        public virtual TValue this[TKey key]
        {
            get
            {
                TValue value;
                bool found = TryGetValue(key, out value);
                if (found)
                    return value;
                else
                    throw new KeyNotFoundException(Strings.KeyNotFound);
            }

            set
            {
                MethodModifiesCollection();
            }
        }

        /// <summary>
        /// Shows the string representation of the dictionary. The string representation contains
        /// a list of the mappings in the dictionary.
        /// </summary>
        /// <returns>The string representation of the dictionary.</returns>
        public override string ToString()
        {
            bool firstItem = true;

            System.Text.StringBuilder builder = new System.Text.StringBuilder();

            builder.Append("{");

            // Call ToString on each item and put it in.
            foreach (KeyValuePair<TKey, TValue> pair in this) {
                if (!firstItem)
                    builder.Append(", ");

                if (pair.Key == null)
                    builder.Append("null");
                else
                    builder.Append(pair.Key.ToString());

                builder.Append("->");

                if (pair.Value == null)
                    builder.Append("null");
                else
                    builder.Append(pair.Value.ToString());

                firstItem = false;
            }

            builder.Append("}");
            return builder.ToString();
        }

       #region IDictionary<TKey,TValue> Members

        /// <summary>
        /// Returns a collection of the keys in this dictionary. 
        /// </summary>
        /// <value>A read-only collection of the keys in this dictionary.</value>
        public virtual ICollection<TKey> Keys
        {
            get { return new KeysCollection(this); }
        }

        /// <summary>
        /// Returns a collection of the values in this dictionary. The ordering of 
        /// values in this collection is the same as that in the Keys collection.
        /// </summary>
        /// <value>A read-only collection of the values in this dictionary.</value>
        public virtual ICollection<TValue> Values
        {
            get { return new ValuesCollection(this); }
        }

        #endregion

        #region ICollection<KeyValuePair<TKey,TValue>> Members

        /// <summary>
        /// Determines if a dictionary contains a given KeyValuePair. This implementation checks to see if the
        /// dictionary contains the given key, and if the value associated with the key is equal to (via object.Equals)
        /// the value.
        /// </summary>
        /// <param name="item">A KeyValuePair containing the Key and Value to check for.</param>
        /// <returns></returns>
        public override bool Contains(KeyValuePair<TKey, TValue> item)
        {
            if (this.ContainsKey(item.Key)) {
                return (object.Equals(this[item.Key], item.Value));
            }
            else {
                return false;
            }
        }

        #endregion

        #region IDictionary Members

        /// <summary>
        /// Adds a key-value pair to the collection. Always throws an exception
        /// indicating that this method is not supported in a read-only dictionary.
        /// </summary>
        /// <param name="key">Key to add to the dictionary.</param>
        /// <param name="value">Value to add to the dictionary.</param>
        /// <exception cref="NotSupportedException">Always thrown.</exception>
        void IDictionary.Add(object key, object value)
        {
            MethodModifiesCollection();
        }

        /// <summary>
        /// Clears this dictionary. Always throws an exception
        /// indicating that this method is not supported in a read-only dictionary.
        /// </summary>
        /// <exception cref="NotSupportedException">Always thrown.</exception>
        void IDictionary.Clear()
        {
            MethodModifiesCollection();
        }

        /// <summary>
        /// Determines if this dictionary contains a key equal to <paramref name="key"/>. The dictionary
        /// is not changed. Calls the (overridden) ContainsKey method. If key is not of the correct
        /// TKey for the dictionary, false is returned.
        /// </summary>
        /// <param name="key">The key to search for.</param>
        /// <returns>True if the dictionary contains key. False if the dictionary does not contain key.</returns>
        bool IDictionary.Contains(object key)
        {
            if (key is TKey || key == null)
                return ContainsKey((TKey)key);
            else
                return false;
        }

        /// <summary>
        /// Removes the key (and associated value) from the collection that is equal to the passed in key. Always throws an exception
        /// indicating that this method is not supported in a read-only dictionary.
        /// </summary>
        /// <param name="key">The key to remove.</param>
        /// <exception cref="NotSupportedException">Always thrown.</exception>
        void IDictionary.Remove(object key)
        {
            MethodModifiesCollection();
        }

        /// <summary>
        /// Returns an enumerator that enumerates all the entries in the dictionary. Each entry is 
        /// returned as a DictionaryEntry.
        /// The entries are enumerated in the same orders as the (overridden) GetEnumerator
        /// method.
        /// </summary>
        /// <returns>An enumerator for enumerating all the elements in the OrderedDictionary.</returns>    
        IDictionaryEnumerator IDictionary.GetEnumerator()
        {
            // You can't implement this directly with an iterator, because iterators automatically implement
            // IEnumerator, not IDictionaryEnumerator. We use the helper class DictionaryEnumeratorWrapper.
            return new DictionaryEnumeratorWrapper(this.GetEnumerator());
        }

        /// <summary>
        /// Returns an enumerator that enumerates all the entries in the dictionary. Each entry is 
        /// returned as a DictionaryEntry.
        /// The entries are enumerated in the same orders as the (overridden) GetEnumerator
        /// method.
        /// </summary>
        /// <returns>An enumerator for enumerating all the elements in the OrderedDictionary.</returns>    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IDictionary)this).GetEnumerator();
        }

        /// <summary>
        /// Returns whether this dictionary is fixed size. 
        /// </summary>
        /// <value>Always returns true.</value>
        bool IDictionary.IsFixedSize
        {
            get { return true; }
        }

        /// <summary>
        /// Returns if this dictionary is read-only. 
        /// </summary>
        /// <value>Always returns true.</value>
        bool IDictionary.IsReadOnly
        {
            get { return true; }
        }

        /// <summary>
        /// Returns a collection of all the keys in the dictionary. The values in this collection will
        /// be enumerated in the same order as the (overridden) GetEnumerator method.
        /// </summary>
        /// <value>The collection of keys.</value>
        ICollection IDictionary.Keys
        {
            get { return new KeysCollection(this); }
        }

        /// <summary>
        /// Returns a collection of all the values in the dictionary. The values in this collection will
        /// be enumerated in the same order as the (overridden) GetEnumerator method.
        /// </summary>
        /// <value>The collection of values.</value>
        ICollection IDictionary.Values
        {
            get { return new ValuesCollection(this); }
        }

        /// <summary>
        /// Gets the value associated with a given key. When getting a value, if this
        /// key is not found in the collection, then null is returned. If the key is not of the correct type 
        /// for this dictionary, null is returned.
        /// </summary>
        /// <value>The value associated with the key, or null if the key was not present.</value>
        /// <exception cref="NotSupportedException">Always thrown from the set accessor, indicating
        /// that the dictionary is read only.</exception>
        object IDictionary.this[object key]
        {
            get
            {
                if (key is TKey || key == null) {
                    TKey theKey = (TKey)key;
                    TValue theValue;

                    // The IDictionary (non-generic) indexer returns null for not found, instead of
                    // throwing an exception like the generic IDictionary indexer.
                    if (TryGetValue(theKey, out theValue))
                        return theValue;
                    else
                        return null;
                }
                else {
                    return null;
                }
            }
            set
            {
                MethodModifiesCollection();
            }
        }

        #endregion

        /// <summary>
        /// Display the contents of the dictionary in the debugger. This is intentionally private, it is called
        /// only from the debugger due to the presence of the DebuggerDisplay attribute. It is similar
        /// format to ToString(), but is limited to 250-300 characters or so, so as not to overload the debugger.
        /// </summary>
        /// <returns>The string representation of the items in the collection, similar in format to ToString().</returns>
        new internal string DebuggerDisplayString()
        {
            const int MAXLENGTH = 250;

            bool firstItem = true;

            System.Text.StringBuilder builder = new System.Text.StringBuilder();

            builder.Append("{");

            // Call ToString on each item and put it in.
            foreach (KeyValuePair<TKey, TValue> pair in this) {
                if (builder.Length >= MAXLENGTH) {
                    builder.Append(", ...");
                    break;
                }

                if (!firstItem)
                    builder.Append(", ");

                if (pair.Key == null)
                    builder.Append("null");
                else
                    builder.Append(pair.Key.ToString());

                builder.Append("->");

                if (pair.Value == null)
                    builder.Append("null");
                else
                    builder.Append(pair.Value.ToString());

                firstItem = false;
            }

            builder.Append("}");
            return builder.ToString();
        }


        #region Keys and Values collections

        /// <summary>
        /// A private class that implements ICollection&lt;TKey&gt; and ICollection for the
        /// Keys collection. The collection is read-only.
        /// </summary>
        [Serializable]
        private sealed class KeysCollection : ReadOnlyCollectionBase<TKey>
        {
            private ReadOnlyDictionaryBase<TKey, TValue> myDictionary;

            /// <summary>
            /// Constructor.
            /// </summary>
            /// <param name="myDictionary">The dictionary this is associated with.</param>
            public KeysCollection(ReadOnlyDictionaryBase<TKey, TValue> myDictionary)
            {
                this.myDictionary = myDictionary;
            }

            public override int Count
            {
                get { return myDictionary.Count; }
            }

            public override IEnumerator<TKey> GetEnumerator()
            {
                foreach (KeyValuePair<TKey, TValue> pair in myDictionary)
                    yield return pair.Key;
            }

            public override bool Contains(TKey key)
            {
                return myDictionary.ContainsKey(key);
            }
        }

        /// <summary>
        /// A private class that implements ICollection&lt;TKey&gt; and ICollection for the
        /// Values collection. The collection is read-only.
        /// </summary>
        [Serializable]
        private sealed class ValuesCollection : ReadOnlyCollectionBase<TValue>
        {
            private ReadOnlyDictionaryBase<TKey, TValue> myDictionary;

            public ValuesCollection(ReadOnlyDictionaryBase<TKey, TValue> myDictionary)
            {
                this.myDictionary = myDictionary;
            }

            public override int Count
            {
                get { return myDictionary.Count; }
            }

            public override IEnumerator<TValue> GetEnumerator()
            {
                foreach (KeyValuePair<TKey, TValue> pair in myDictionary)
                    yield return pair.Value;
            }
        }

        #endregion

        /// <summary>
        /// A class that wraps a IDictionaryEnumerator around an IEnumerator that
        /// enumerates KeyValuePairs. This is useful in implementing IDictionary, because
        /// IEnumerator can be implemented with an iterator, but IDictionaryEnumerator cannot.
        /// </summary>
        [Serializable]
        private class DictionaryEnumeratorWrapper : IDictionaryEnumerator
        {
            private IEnumerator<KeyValuePair<TKey, TValue>> enumerator;

            /// <summary>
            /// Constructor.
            /// </summary>
            /// <param name="enumerator">The enumerator of KeyValuePairs that is being wrapped.</param>
            public DictionaryEnumeratorWrapper(IEnumerator<KeyValuePair<TKey, TValue>> enumerator)
            {
                this.enumerator = enumerator;
            }

            public DictionaryEntry Entry
            {
                get
                {
                    KeyValuePair<TKey, TValue> pair = enumerator.Current;
                    DictionaryEntry entry = new DictionaryEntry();
                    if (pair.Key != null)
                        entry.Key = pair.Key;
                    entry.Value = pair.Value;

                    return entry;
                }
            }

            public object Key
            {
                get
                {
                    KeyValuePair<TKey, TValue> pair = enumerator.Current;

                    return pair.Key;
                }
            }

            public object Value
            {
                get
                {
                    KeyValuePair<TKey, TValue> pair = enumerator.Current;
                    return pair.Value;
                }
            }

            public void Reset()
            {
                throw new NotSupportedException(Strings.ResetNotSupported);
            }


            public bool MoveNext()
            {
                return enumerator.MoveNext();
            }


            public object Current
            {
                get
                {
                    return Entry;
                }
            }
        }
    }
}



www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.