#region Apache License // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you 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 using System; using System.Collections; #if NETSTANDARD1_3 using System.Reflection; #endif using System.Runtime.Serialization; using System.Xml; namespace log4net.Util { /// /// String keyed object map that is read only. /// /// /// /// This collection is readonly and cannot be modified. /// /// /// While this collection is serializable only member /// objects that are serializable will /// be serialized along with this collection. /// /// /// Nicko Cadell /// Gert Driesen #if NETCF public class ReadOnlyPropertiesDictionary : IDictionary #else [Serializable] public class ReadOnlyPropertiesDictionary : ISerializable, IDictionary #endif { #region Private Instance Fields /// /// The Hashtable used to store the properties data /// private readonly Hashtable m_hashtable = new Hashtable(); #endregion Private Instance Fields #region Public Instance Constructors /// /// Constructor /// /// /// /// Initializes a new instance of the class. /// /// public ReadOnlyPropertiesDictionary() { } /// /// Copy Constructor /// /// properties to copy /// /// /// Initializes a new instance of the class. /// /// public ReadOnlyPropertiesDictionary(ReadOnlyPropertiesDictionary propertiesDictionary) { foreach(DictionaryEntry entry in propertiesDictionary) { InnerHashtable.Add(entry.Key, entry.Value); } } #endregion Public Instance Constructors #region Private Instance Constructors #if !NETCF /// /// Deserialization constructor /// /// The that holds the serialized object data. /// The that contains contextual information about the source or destination. /// /// /// Initializes a new instance of the class /// with serialized data. /// /// protected ReadOnlyPropertiesDictionary(SerializationInfo info, StreamingContext context) { foreach(SerializationEntry entry in info) { // The keys are stored as Xml encoded names InnerHashtable[XmlConvert.DecodeName(entry.Name)] = entry.Value; } } #endif #endregion Protected Instance Constructors #region Public Instance Properties /// /// Gets the key names. /// /// An array of all the keys. /// /// /// Gets the key names. /// /// public string[] GetKeys() { string[] keys = new String[InnerHashtable.Count]; InnerHashtable.Keys.CopyTo(keys, 0); return keys; } /// /// Gets or sets the value of the property with the specified key. /// /// /// The value of the property with the specified key. /// /// The key of the property to get or set. /// /// /// The property value will only be serialized if it is serializable. /// If it cannot be serialized it will be silently ignored if /// a serialization operation is performed. /// /// public virtual object this[string key] { get { return InnerHashtable[key]; } set { throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); } } #endregion Public Instance Properties #region Public Instance Methods /// /// Test if the dictionary contains a specified key /// /// the key to look for /// true if the dictionary contains the specified key /// /// /// Test if the dictionary contains a specified key /// /// public bool Contains(string key) { return InnerHashtable.Contains(key); } #endregion /// /// The hashtable used to store the properties /// /// /// The internal collection used to store the properties /// /// /// /// The hashtable used to store the properties /// /// protected Hashtable InnerHashtable { get { return m_hashtable; } } #region Implementation of ISerializable #if !NETCF /// /// Serializes this object into the provided. /// /// The to populate with data. /// The destination for this serialization. /// /// /// Serializes this object into the provided. /// /// #if NET_4_0 || MONO_4_0 || NETSTANDARD [System.Security.SecurityCritical] #endif #if !NETCF && !NETSTANDARD1_3 [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter = true)] #endif public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { foreach(DictionaryEntry entry in InnerHashtable.Clone() as IDictionary) { string entryKey = entry.Key as string; object entryValue = entry.Value; // If value is serializable then we add it to the list #if NETSTANDARD1_3 bool isSerializable = entryValue.GetType().GetTypeInfo().IsSerializable; #else bool isSerializable = entryValue.GetType().IsSerializable; #endif if (entryKey != null && entryValue != null && isSerializable) { // Store the keys as an Xml encoded local name as it may contain colons (':') // which are NOT escaped by the Xml Serialization framework. // This must be a bug in the serialization framework as we cannot be expected // to know the implementation details of all the possible transport layers. info.AddValue(XmlConvert.EncodeLocalName(entryKey), entryValue); } } } #endif #endregion Implementation of ISerializable #region Implementation of IDictionary /// /// See /// IDictionaryEnumerator IDictionary.GetEnumerator() { return InnerHashtable.GetEnumerator(); } /// /// See /// /// void IDictionary.Remove(object key) { throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); } /// /// See /// /// /// bool IDictionary.Contains(object key) { return InnerHashtable.Contains(key); } /// /// Remove all properties from the properties collection /// public virtual void Clear() { throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); } /// /// See /// /// /// void IDictionary.Add(object key, object value) { throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); } /// /// See /// bool IDictionary.IsReadOnly { get { return true; } } /// /// See /// object IDictionary.this[object key] { get { if (!(key is string)) throw new ArgumentException("key must be a string"); return InnerHashtable[key]; } set { throw new NotSupportedException("This is a Read Only Dictionary and can not be modified"); } } /// /// See /// ICollection IDictionary.Values { get { return InnerHashtable.Values; } } /// /// See /// ICollection IDictionary.Keys { get { return InnerHashtable.Keys; } } /// /// See /// bool IDictionary.IsFixedSize { get { return InnerHashtable.IsFixedSize; } } #endregion #region Implementation of ICollection /// /// See /// /// /// void ICollection.CopyTo(Array array, int index) { InnerHashtable.CopyTo(array, index); } /// /// See /// bool ICollection.IsSynchronized { get { return InnerHashtable.IsSynchronized; } } /// /// The number of properties in this collection /// public int Count { get { return InnerHashtable.Count; } } /// /// See /// object ICollection.SyncRoot { get { return InnerHashtable.SyncRoot; } } #endregion #region Implementation of IEnumerable /// /// See /// IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)InnerHashtable).GetEnumerator(); } #endregion } }