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.