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
}
}