using System; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; namespace RanWahle.Blog { /// /// This class implements Bi-directional dictionary /// /// The dictionary Key (acts also as value) /// The dictionary value (acts also as key) /// /// Because values acts also as keys, they should not repeat one another /// If a value is added twice - en exception is thrown (as in key in regular dictionary) /// This class won't support key and value of the same type. /// public class BiDirectionalDictionary : IDictionary, ICollection>, IEnumerable>, IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback { #region Members private Dictionary keyValueDic; private Dictionary valueKeyDic; #endregion #region Ctor public BiDirectionalDictionary() { if (typeof(TKey) == typeof(TValue)) { throw new NotSupportedException("This class cannot suport keys and values of the same type"); } keyValueDic = new Dictionary(); valueKeyDic = new Dictionary(); } #endregion #region Proeprties /// /// Gets a collection containing the keys of the dictionary /// public Dictionary.KeyCollection Keys { get { return keyValueDic.Keys; } } /// /// Gets a collection containing the values of the dictionary /// public Dictionary.ValueCollection Values { get { return keyValueDic.Values; } } /// /// Gets or sets the value of thedictionary by the TKey /// /// TKey /// public TValue this[TKey key] { get { return keyValueDic[key]; } set { if (valueKeyDic.ContainsKey(value)) { keyValueDic.Remove(valueKeyDic[value]); } keyValueDic[key] = value; valueKeyDic[value] = key; } } public TKey this[TValue valueAsKey] { get { return valueKeyDic[valueAsKey]; } set { if (keyValueDic.ContainsKey(value)) { valueKeyDic.Remove(keyValueDic[value]); } keyValueDic[value] = valueAsKey; valueKeyDic[valueAsKey] = value; } } #endregion #region Methods public Dictionary.Enumerator GetEnumerator() { return keyValueDic.GetEnumerator(); } /// /// Adds the specified key and value to the dictionary /// /// Dictionary key /// Dictionary value public void Add(TKey key, TValue value) { //Validate if (this.ContainsKey(key)) { throw new ArgumentException(string.Format("The key {0} is already exist in the dictionary", key)); } if (this.ContainsValue(value)) { throw new ArgumentException(string.Format("The value {0} is already exist in the dictonary", value)); } keyValueDic.Add(key, value); valueKeyDic.Add(value, key); } /// /// Removes the value with it specified key from hte dictionary /// /// Key to remove /// True if item removed, false otherwise public bool Remove(TKey key) { TValue value = keyValueDic[key]; return Remove(key, value); } /// /// Removes the specified value with it's key from the dictionary /// /// Value to remove public bool Remove(TValue value) { TKey key = valueKeyDic[value]; return Remove(key, value); } /// /// /// /// /// /// True if item removed, false otherwise private bool Remove(TKey key, TValue value) { return keyValueDic.Remove(key) && valueKeyDic.Remove(value); } #endregion #region ICollection> Members public void Add(KeyValuePair item) { Add(item.Key, item.Value); } public void Clear() { keyValueDic.Clear(); valueKeyDic.Clear(); } public bool Contains(KeyValuePair item) { return keyValueDic.ContainsKey(item.Key) && keyValueDic[item.Key].Equals(item.Value); } /// /// Gets the number of key/value pairs contained in the System.Collections.Generic.Dictionary<TKey,TValue>. /// public int Count { get { return keyValueDic.Count; } } public bool Remove(KeyValuePair item) { return keyValueDic.Remove(item.Key) && valueKeyDic.Remove(item.Value); } #endregion #region IEnumerable> Members IEnumerator> IEnumerable>.GetEnumerator() { return keyValueDic.GetEnumerator(); } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } #endregion #region ICollection> Members /// /// Copies the dictionary to the given array /// starting in thew given arrayIndex /// /// Array to copy to /// Starting index public void CopyTo(KeyValuePair[] array, int arrayIndex) { int tempIndex = arrayIndex; foreach (KeyValuePair pair in this) { array[tempIndex] = pair; tempIndex++; } } public bool IsReadOnly { get { return true; } } #endregion /// /// Determines whether the BiDirectionalDictionary<TKey,TValue> /// contains the specified key. /// /// /// The key to locate in the BiDirectionalDictionar<TKey,TValue>. /// /// /// true if the System.Collections.Generic.Dictionary contains an /// element with the specified key; otherwise, false. /// /// Key is null public bool ContainsKey(TKey key) { return this.keyValueDic.ContainsKey(key); } /// /// Determines whether the BiDirectionalDictionary<TKey,TValue> /// contains the specified value. /// /// /// The value to locate in the BiDirectionalDictionar<TKey,TValue>. /// /// /// true if the SBiDirectionalDictionar<TKey,TValue> contains an /// element with the specified key; otherwise, false. /// /// Value is null public bool ContainsValue(TValue value) { return this.valueKeyDic.ContainsKey(value); } #region IDeserializationCallback Members public void OnDeserialization(object sender) { this.keyValueDic.OnDeserialization(sender); } #endregion #region ISerializable Members public void GetObjectData(SerializationInfo info, StreamingContext context) { this.keyValueDic.GetObjectData(info, context); } #endregion #region ICollection Members /// /// Copies the dictionary to the given array /// starting in thew given arrayIndex /// /// Array to copy to /// Starting index public void CopyTo(Array array, int index) { this.CopyTo(array as KeyValuePair[], index); } bool ICollection.IsSynchronized { get { return (this.keyValueDic as ICollection).IsSynchronized; } } object ICollection.SyncRoot { get { return (this.keyValueDic as ICollection).SyncRoot; } } #endregion #region IDictionary Members bool IDictionary.IsFixedSize { get { return (this.keyValueDic as IDictionary).IsFixedSize; } } #endregion #region ICollection Members int ICollection.Count { get { return this.Count; } } #endregion #region IDictionary Members public void Add(object key, object value) { this.Add((TKey)key, (TValue)value); } public bool Contains(object key) { return this.Contains((TKey)key); } IDictionaryEnumerator IDictionary.GetEnumerator() { return this.GetEnumerator(); } ICollection IDictionary.Keys { get { return this.Keys; } } public void Remove(object key) { this.Remove((TKey)key); } ICollection IDictionary.Values { get { return this.Values; } } public object this[object key] { get { return this[(TKey)key]; } set { this[(TKey)key] = (TValue)value; } } #endregion #region IDictionary Members ICollection IDictionary.Keys { get { return this.Keys; } } bool IDictionary.Remove(TKey key) { return this.Remove(key); } /// /// Gets the value associated with the specified key. /// /// The key of the value to get. /// /// When this method returns, contains the value associated with the specified /// key, if the key is found; otherwise, the default value for the type of the /// value parameter. This parameter is passed uninitialized. /// /// true if the System.Collections.Generic.Dictionary<TKey,TValue> contains an /// element with the specified key; otherwise, false. /// /// /// key is null. /// public bool TryGetValue(TKey key, out TValue value) { return keyValueDic.TryGetValue(key, out value); } /// /// Tries to get key out of the dictionary. /// Acts as the opposite of TryGetValue /// /// Value (act as key in the opposite direction /// Key (act as value in the opposite direction) /// True if key exists, false otherwise public bool TryGetKey(TValue value, out TKey key) { return valueKeyDic.TryGetValue(value, out key); } /// /// Gets all dictionbary values /// ICollection IDictionary.Values { get { return this.Values; } } #endregion } }