using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
namespace Caliburn.MemoryManagement
{
///
/// Represents a dictionary mapping keys to values.
///
///
///
/// Provides the plumbing for the portions of IDictionary which can reasonably be implemented without any
/// dependency on the underlying representation of the dictionary.
///
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(PREFIX + "DictionaryDebugView`2" + SUFFIX)]
public abstract class BaseDictionary : IDictionary
{
private const string PREFIX = "System.Collections.Generic.Mscorlib_";
private const string SUFFIX = ",mscorlib,Version=2.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089";
private KeyCollection keys;
private ValueCollection values;
#region IDictionary Members
public abstract int Count { get; }
public abstract void Clear();
public abstract void Add(TKey key, TValue value);
public abstract bool ContainsKey(TKey key);
public abstract bool Remove(TKey key);
public abstract bool TryGetValue(TKey key, out TValue value);
public abstract IEnumerator> GetEnumerator();
public bool IsReadOnly
{
get { return false; }
}
public ICollection Keys
{
get
{
if(keys == null)
keys = new KeyCollection(this);
return keys;
}
}
public ICollection Values
{
get
{
if(values == null)
values = new ValueCollection(this);
return values;
}
}
public TValue this[TKey key]
{
get
{
TValue value;
if(!TryGetValue(key, out value))
throw new KeyNotFoundException();
return value;
}
set { SetValue(key, value); }
}
public void Add(KeyValuePair item)
{
Add(item.Key, item.Value);
}
public bool Contains(KeyValuePair item)
{
TValue value;
if(!TryGetValue(item.Key, out value))
return false;
return EqualityComparer.Default.Equals(value, item.Value);
}
public void CopyTo(KeyValuePair[] array, int arrayIndex)
{
Copy(this, array, arrayIndex);
}
public bool Remove(KeyValuePair item)
{
if(!Contains(item))
return false;
return Remove(item.Key);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
protected abstract void SetValue(TKey key, TValue value);
private static void Copy(ICollection source, T[] array, int arrayIndex)
{
if(array == null)
throw new ArgumentNullException("array");
if(arrayIndex < 0 || arrayIndex > array.Length)
throw new ArgumentOutOfRangeException("arrayIndex");
if((array.Length - arrayIndex) < source.Count)
throw new ArgumentException("Destination array is not large enough. Check array.Length and arrayIndex.");
foreach(T item in source)
array[arrayIndex++] = item;
}
#region Nested type: Collection
private abstract class Collection : ICollection
{
protected readonly IDictionary dictionary;
protected Collection(IDictionary dictionary)
{
this.dictionary = dictionary;
}
#region ICollection Members
public int Count
{
get { return dictionary.Count; }
}
public bool IsReadOnly
{
get { return true; }
}
public void CopyTo(T[] array, int arrayIndex)
{
Copy(this, array, arrayIndex);
}
public virtual bool Contains(T item)
{
foreach(T element in this)
if(EqualityComparer.Default.Equals(element, item))
return true;
return false;
}
public IEnumerator GetEnumerator()
{
foreach(KeyValuePair pair in dictionary)
yield return GetItem(pair);
}
public bool Remove(T item)
{
throw new NotSupportedException("Collection is read-only.");
}
public void Add(T item)
{
throw new NotSupportedException("Collection is read-only.");
}
public void Clear()
{
throw new NotSupportedException("Collection is read-only.");
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
protected abstract T GetItem(KeyValuePair pair);
}
#endregion
#region Nested type: KeyCollection
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(PREFIX + "DictionaryKeyCollectionDebugView`2" + SUFFIX)]
private class KeyCollection : Collection
{
public KeyCollection(IDictionary dictionary)
: base(dictionary) {}
protected override TKey GetItem(KeyValuePair pair)
{
return pair.Key;
}
public override bool Contains(TKey item)
{
return dictionary.ContainsKey(item);
}
}
#endregion
#region Nested type: ValueCollection
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(PREFIX + "DictionaryValueCollectionDebugView`2" + SUFFIX)]
private class ValueCollection : Collection
{
public ValueCollection(IDictionary dictionary)
: base(dictionary) {}
protected override TValue GetItem(KeyValuePair pair)
{
return pair.Value;
}
}
#endregion
}
}