#region Apache License 2.0 /* Nuclex .NET Framework Copyright (C) 2002-2024 Markus Ewald / Nuclex Development Labs Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #endregion // Apache License 2.0 using System; using System.Collections.Generic; using System.Collections; using System.Runtime.Serialization; namespace Nuclex.Support.Collections { /// Wraps a dictionary and prevents users from modifying it /// Type of the keys used in the dictionary /// Type of the values used in the dictionary #if !NO_SERIALIZATION [Serializable] #endif public class ReadOnlyDictionary : #if !NO_SERIALIZATION ISerializable, IDeserializationCallback, #endif IDictionary, IDictionary { #if !NO_SERIALIZATION #region class SerializedDictionary /// /// Dictionary wrapped used to reconstruct a serialized read only dictionary /// private class SerializedDictionary : Dictionary { /// /// Initializes a new instance of the System.WeakReference class, using deserialized /// data from the specified serialization and stream objects. /// /// /// An object that holds all the data needed to serialize or deserialize the /// current System.WeakReference object. /// /// /// (Reserved) Describes the source and destination of the serialized stream /// specified by info. /// /// /// The info parameter is null. /// public SerializedDictionary(SerializationInfo info, StreamingContext context) : base(info, context) { } } #endregion // class SerializedDictionary /// /// Initializes a new instance of the System.WeakReference class, using deserialized /// data from the specified serialization and stream objects. /// /// /// An object that holds all the data needed to serialize or deserialize the /// current System.WeakReference object. /// /// /// (Reserved) Describes the source and destination of the serialized stream /// specified by info. /// /// /// The info parameter is null. /// protected ReadOnlyDictionary(SerializationInfo info, StreamingContext context) : this(new SerializedDictionary(info, context)) { } #endif // !NO_SERIALIZATION /// Initializes a new read-only dictionary wrapper /// Dictionary that will be wrapped public ReadOnlyDictionary(IDictionary dictionary) { this.typedDictionary = dictionary; this.objectDictionary = (this.typedDictionary as IDictionary); } /// Whether the directory is write-protected public bool IsReadOnly { get { return true; } } /// /// Determines whether the specified KeyValuePair is contained in the Dictionary /// /// KeyValuePair that will be checked for /// True if the provided KeyValuePair was contained in the Dictionary public bool Contains(KeyValuePair item) { return this.typedDictionary.Contains(item); } /// Determines whether the Dictionary contains the specified key /// Key that will be checked for /// /// True if an entry with the specified key was contained in the Dictionary /// public bool ContainsKey(KeyType key) { return this.typedDictionary.ContainsKey(key); } /// Copies the contents of the Dictionary into an array /// Array the Dictionary will be copied into /// /// Starting index at which to begin filling the destination array /// public void CopyTo(KeyValuePair[] array, int arrayIndex) { this.typedDictionary.CopyTo(array, arrayIndex); } /// Number of elements contained in the Dictionary public int Count { get { return this.typedDictionary.Count; } } /// Creates a new enumerator for the Dictionary /// The new Dictionary enumerator public IEnumerator> GetEnumerator() { return this.typedDictionary.GetEnumerator(); } /// Collection of all keys contained in the Dictionary public ICollection Keys { get { if(this.readonlyKeyCollection == null) { this.readonlyKeyCollection = new ReadOnlyCollection( this.typedDictionary.Keys ); } return this.readonlyKeyCollection; } } /// Collection of all values contained in the Dictionary public ICollection Values { get { if(this.readonlyValueCollection == null) { this.readonlyValueCollection = new ReadOnlyCollection( this.typedDictionary.Values ); } return this.readonlyValueCollection; } } /// /// Attempts to retrieve the item with the specified key from the Dictionary /// /// Key of the item to attempt to retrieve /// /// Output parameter that will receive the key upon successful completion /// /// /// True if the item was found and has been placed in the output parameter /// public bool TryGetValue(KeyType key, out ValueType value) { return this.typedDictionary.TryGetValue(key, out value); } /// Accesses an item in the Dictionary by its key /// Key of the item that will be accessed public ValueType this[KeyType key] { get { return this.typedDictionary[key]; } } #region IDictionary<,> implementation /// Inserts an item into the Dictionary /// Key under which to add the new item /// Item that will be added to the Dictionary void IDictionary.Add(KeyType key, ValueType value) { throw new NotSupportedException( "Adding items is not supported by the read-only Dictionary" ); } /// Removes the item with the specified key from the Dictionary /// Key of the elementes that will be removed /// True if an item with the specified key was found and removed bool IDictionary.Remove(KeyType key) { throw new NotSupportedException( "Removing items is not supported by the read-only Dictionary" ); } /// Accesses an item in the Dictionary by its key /// Key of the item that will be accessed ValueType IDictionary.this[KeyType key] { get { return this.typedDictionary[key]; } set { throw new NotSupportedException( "Assigning items is not supported in a read-only Dictionary" ); } } #endregion #region IEnumerable implementation /// Returns a new object enumerator for the Dictionary /// The new object enumerator System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return (this.typedDictionary as IEnumerable).GetEnumerator(); } #endregion #region IDictionary implementation /// Removes all items from the Dictionary void IDictionary.Clear() { throw new NotSupportedException( "Clearing is not supported in a read-only Dictionary" ); } /// Adds an item into the Dictionary /// Key under which the item will be added /// Item that will be added void IDictionary.Add(object key, object value) { throw new NotSupportedException( "Adding items is not supported in a read-only Dictionary" ); } /// Determines whether the specified key exists in the Dictionary /// Key that will be checked for /// True if an item with the specified key exists in the Dictionary bool IDictionary.Contains(object key) { return this.objectDictionary.Contains(key); } /// Whether the size of the Dictionary is fixed bool IDictionary.IsFixedSize { get { return this.objectDictionary.IsFixedSize; } } /// Returns a collection of all keys in the Dictionary ICollection IDictionary.Keys { get { if(this.readonlyKeyCollection == null) { this.readonlyKeyCollection = new ReadOnlyCollection( this.typedDictionary.Keys ); } return this.readonlyKeyCollection; } } /// Returns a collection of all values stored in the Dictionary ICollection IDictionary.Values { get { if(this.readonlyValueCollection == null) { this.readonlyValueCollection = new ReadOnlyCollection( this.typedDictionary.Values ); } return this.readonlyValueCollection; } } /// Removes an item from the Dictionary /// Key of the item that will be removed void IDictionary.Remove(object key) { throw new NotSupportedException( "Removing is not supported by the read-only Dictionary" ); } /// Accesses an item in the Dictionary by its key /// Key of the item that will be accessed /// The item with the specified key object IDictionary.this[object key] { get { return this.objectDictionary[key]; } set { throw new NotSupportedException( "Assigning items is not supported by the read-only Dictionary" ); } } #endregion // IDictionary implementation #region IDictionaryEnumerator implementation /// Returns a new entry enumerator for the dictionary /// The new entry enumerator IDictionaryEnumerator IDictionary.GetEnumerator() { return this.objectDictionary.GetEnumerator(); } #endregion // IDictionaryEnumerator implementation #region ICollection<> implementation /// Inserts an already prepared element into the Dictionary /// Prepared element that will be added to the Dictionary void ICollection>.Add( KeyValuePair item ) { throw new NotSupportedException( "Adding items is not supported by the read-only Dictionary" ); } /// Removes all items from the Dictionary void ICollection>.Clear() { throw new NotSupportedException( "Clearing is not supported in a read-only Dictionary" ); } /// Removes all items from the Dictionary /// Item that will be removed from the Dictionary bool ICollection>.Remove( KeyValuePair itemToRemove ) { throw new NotSupportedException( "Removing items is not supported in a read-only Dictionary" ); } #endregion #region ICollection implementation /// Copies the contents of the Dictionary into an array /// Array the Dictionary contents will be copied into /// /// Starting index at which to begin filling the destination array /// void ICollection.CopyTo(Array array, int index) { this.objectDictionary.CopyTo(array, index); } /// Whether the Dictionary is synchronized for multi-threaded usage bool ICollection.IsSynchronized { get { return this.objectDictionary.IsSynchronized; } } /// Synchronization root on which the Dictionary locks object ICollection.SyncRoot { get { return this.objectDictionary.SyncRoot; } } #endregion #if !NO_SERIALIZATION #region ISerializable implementation /// Serializes the Dictionary /// /// Provides the container into which the Dictionary will serialize itself /// /// /// Contextual informations about the serialization environment /// void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { (this.typedDictionary as ISerializable).GetObjectData(info, context); } /// Called after all objects have been successfully deserialized /// Nicht unterstützt void IDeserializationCallback.OnDeserialization(object sender) { (this.typedDictionary as IDeserializationCallback).OnDeserialization(sender); } #endregion #endif //!NO_SERIALIZATION /// The wrapped Dictionary under its type-safe interface private IDictionary typedDictionary; /// The wrapped Dictionary under its object interface private IDictionary objectDictionary; /// ReadOnly wrapper for the keys collection of the Dictionary private ReadOnlyCollection readonlyKeyCollection; /// ReadOnly wrapper for the values collection of the Dictionary private ReadOnlyCollection readonlyValueCollection; } } // namespace Nuclex.Support.Collections