Laden...

Dictionary das mehrere Objekte pro Key als Liste unterstürzt....

Erstellt von dr4g0n76 vor 16 Jahren Letzter Beitrag vor 16 Jahren 2.570 Views
dr4g0n76 Themenstarter:in
2.921 Beiträge seit 2005
vor 16 Jahren
Dictionary das mehrere Objekte pro Key als Liste unterstürzt....

Dieses Dictionary unterstützt ein hinzufzufügen von mehreren Objekten zum gleichen Key.

Sicher lässt sich das auch anders lösen, wollte aber die Komponente hier nicht vorenthalten.


using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace Library.ExtendedBaseTypes.Generics
{
    /// <summary>
    /// This is Thrown if a list couldn't be copied correctly
    /// </summary>
    public class CCustomDictionaryCloneException : Exception
    {
        private object m_oObjectValue = null;
        private object m_oObjectKey = null;

        /// <summary>
        /// Gets the object value.
        /// </summary>
        /// <value>The object value.</value>
        public object ObjectValue
        {
            get { return this.m_oObjectValue; }
        }

        /// <summary>
        /// Gets the object key.
        /// </summary>
        /// <value>The object key.</value>
        public object ObjectKey
        {
            get { return this.m_oObjectKey; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CCustomDictionaryCloneException"/> class.
        /// </summary>
        public CCustomDictionaryCloneException()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CCustomDictionaryCloneException"/> class.
        /// </summary>
        /// <param name="_oKey">The _o key.</param>
        /// <param name="_oValue">The _o value.</param>
        public CCustomDictionaryCloneException(object _oKey, object _oValue)
        {
            this.m_oObjectKey = _oKey;
            this.m_oObjectValue = _oValue;
        }
    }

    /// <summary>
    /// Use this class to handle collections with several objects be added to the same key...
    /// this list is a common class.
    /// so the key has to be of the type K
    /// and the value has to be of the type T
    /// internally this is handled as a
    /// Dictionary with a generic list of type T as a value-Type
    /// </summary>
    /// <typeparam name="K"></typeparam>
    /// <typeparam name="T"></typeparam>
    [Serializable]
    public class CCustomDictionary<K, T> : Dictionary<K, List<T>>, ICloneable
    {
        private bool m_bThrowCloneModeException = true;

        public bool ThrowCloneModeException
        {
            get { return this.m_bThrowCloneModeException; }
            set { this.m_bThrowCloneModeException = value; }
        }


        /// <summary>
        /// Adds the specified _k.
        /// </summary>
        /// <param name="_k">The _k.</param>
        /// <param name="_t">The _t.</param>
        public virtual void Add(K _k, T _t)
        {
            if (this.ContainsKey(_k))
            {
                List<T> list = this[_k];
                list.Add(_t);
                this[_k] = list;
            }
            else
            {
                List<T> list = new List<T>();
                list.Add(_t);
                base.Add(_k, list);
            }
        }

        /// <summary>
        /// Test if object is contained at current key position...
        /// </summary>
        /// <param name="_k"></param>
        /// <param name="_t"></param>
        /// <returns></returns>
        public virtual bool ContainsObject(K _k, T _t)
        {
            if (this.ContainsKey(_k))
            {
                return ((List<T>)this[_k]).Contains(_t);
            }
            return false;
        }
        /// <summary>
        /// Removes the specified _k.
        /// </summary>
        /// <param name="_k">The _k.</param>
        /// <param name="_nIndex">Index of the _n.</param>
        public virtual void Remove(K _k, int _nIndex)
        {
            List<T> list = this[_k];
            list.RemoveAt(_nIndex);
            this[_k] = list;
        }

        /// <summary>
        /// Removes the specified _k.
        /// </summary>
        /// <param name="_k">The _k.</param>
        /// <param name="_nRangeStart">The _n range start.</param>
        /// <param name="_nRangeEnd">The _n range end.</param>
        public virtual void Remove(K _k, int _nRangeStart, int _nRangeEnd)
        {
            List<T> list = this[_k];
            list.RemoveRange(_nRangeStart, _nRangeEnd - _nRangeStart);
            this[_k] = list;
        }

        /// <summary>
        /// Gets the <see cref="T"/> with the specified _k.
        /// </summary>
        /// <value></value>
        public T this[K _k, int _nIndex]
        {
            get
            {
                List<T> list = this[_k];
                return list[_nIndex];
            }
        }

        /// <summary>
        /// Get list of given elements from specified index...
        /// </summary>
        /// <param name="_k"></param>
        /// <param name="_nStartIndex"></param>
        /// <param name="_nCount"></param>
        /// <returns></returns>
        public virtual List<T> this[K _k, int _nStartIndex, int _nCount]
        {
            get { return ((List<T>)this[_k]).GetRange(_nStartIndex, _nCount); }
        }

        /// <summary>
        /// gets the object count of a given key.
        /// </summary>
        /// <param name="_k">The _k.</param>
        /// <returns></returns>
        public virtual int ObjectCount(K _k)
        {
            return ((List<T>)this[_k]).Count;
        }

        /// <summary>
        /// Bestimmt, ob das angegebene <see cref="T:System.Object"></see> und das aktuelle <see cref="T:System.Object"></see> gleich sind.
        /// </summary>
        /// <param name="obj">Das <see cref="T:System.Object"></see>, das mit dem aktuellen <see cref="T:System.Object"></see> verglichen werden soll.</param>
        /// <returns>
        /// true, wenn das angegebene <see cref="T:System.Object"></see> gleich dem aktuellen <see cref="T:System.Object"></see> ist, andernfalls false.
        /// </returns>
        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

        /// <summary>
        /// Fungiert als Hashfunktion für einen bestimmten Typ. <see cref="M:System.Object.GetHashCode"></see> eignet sich für die Verwendung in Hashalgorithmen und Hashdatenstrukturen, z. B. in einer Hashtabelle.
        /// </summary>
        /// <returns>
        /// Ein Hashcode für das aktuelle <see cref="T:System.Object"></see>.
        /// </returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        /// <summary>
        /// Implementiert die <see cref="T:System.Runtime.Serialization.ISerializable"></see>-Schnittstelle und gibt die zum Serialisieren der <see cref="T:System.Collections.Generic.Dictionary`2"></see>-Instanz erforderlichen Daten zurück.
        /// </summary>
        /// <param name="info">Ein <see cref="T:System.Runtime.Serialization.SerializationInfo"></see>-Objekt mit den zum Serialisieren der <see cref="T:System.Collections.Generic.Dictionary`2"></see>-Instanz erforderlichen Informationen.</param>
        /// <param name="context">Eine <see cref="T:System.Runtime.Serialization.StreamingContext"></see>-Struktur, die die Quelle und das Ziel des serialisierten Streams enthält, der der <see cref="T:System.Collections.Generic.Dictionary`2"></see>-Instanz zugeordnet ist.</param>
        /// <exception cref="T:System.ArgumentNullException">info ist null.</exception>
        public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
        {
            base.GetObjectData(info, context);
        }

        /// <summary>
        /// Implementiert die <see cref="T:System.Runtime.Serialization.ISerializable"></see>-Schnittstelle und löst das Deserialisierungsereignis aus, sobald die Deserialisierung abgeschlossen ist.
        /// </summary>
        /// <param name="sender">Die Quelle des Deserialisierungsereignisses.</param>
        /// <exception cref="T:System.Runtime.Serialization.SerializationException">Das der aktuellen <see cref="T:System.Collections.Generic.Dictionary`2"></see>-Instanz zugeordnete <see cref="T:System.Runtime.Serialization.SerializationInfo"></see>-Objekt ist ungültig.</exception>
        public override void OnDeserialization(object sender)
        {
            base.OnDeserialization(sender);
        }

        /// <summary>
        /// Gibt einen <see cref="T:System.String"></see> zurück, der den aktuellen <see cref="T:System.Object"></see> darstellt.
        /// </summary>
        /// <returns>
        /// Ein <see cref="T:System.String"></see>, der den aktuellen <see cref="T:System.Object"></see> darstellt.
        /// </returns>
        public override string ToString()
        {
            return base.ToString();
        }

        #region ICloneable Member

        /// <summary>
        /// Erstellt ein neues Objekt, das eine Kopie der aktuellen Instanz darstellt.
        /// </summary>
        /// <returns>
        /// Ein neues Objekt, das eine Kopie dieser Instanz darstellt.
        /// </returns>
             public virtual object Clone()
        {
            CCustomDictionary<K, T> aDict = (CCustomDictionary<K, T>)this.MemberwiseClone();
            IEnumerator enumerator = this.GetEnumerator();
            while (enumerator.MoveNext())
            {
                KeyValuePair<K, List<T>> keyValuePair = (KeyValuePair<K, List<T>>)enumerator.Current;
                List<T> list = (List<T>)keyValuePair.Value;
                List<T> listCloned = new List<T>();
                foreach (object oObjectToClone in list)
                {
                    if (oObjectToClone is ICloneable)
                    {
                        listCloned.Add((T)(((ICloneable)oObjectToClone).Clone()));
                    }
                }
                //check for each entry if cloned correctly
                if (this.m_bThrowCloneModeException)
                {
                    if (listCloned.Count != list.Count)
                    {
                        throw new CCustomDictionaryCloneException(keyValuePair.Key, keyValuePair.Value);
                    }
                }
                foreach (object oClonedElement in listCloned)
                {
                    aDict.Add((K)((ICloneable)keyValuePair.Key).Clone(), (T)oClonedElement);
                }
                if (this.m_bThrowCloneModeException)
                {
                    //check if entry count match (old list <> new list)
                    if (aDict.Keys.Count != this.Keys.Count)
                    {
                        throw new CCustomDictionaryCloneException(keyValuePair.Key, keyValuePair.Value);
                    }
                }
            }
            return aDict;
        }
        #endregion
    }
}

Schlagwörter: Dictionary

Seit der Erkenntnis, dass der Mensch eine Nachricht ist, erweist sich seine körperliche Existenzform als überflüssig.