| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 | 
							- namespace Caliburn.Micro.Core {
 
-     using System;
 
-     using System.Collections;
 
-     using System.Collections.Generic;
 
-     using System.Linq;
 
-     /// <summary>
 
-     /// A dictionary in which the values are weak references.
 
-     /// </summary>
 
-     /// <typeparam name="TKey">The type of keys in the dictionary.</typeparam>
 
-     /// <typeparam name="TValue">The type of values in the dictionary.</typeparam>
 
-     internal class WeakValueDictionary<TKey, TValue> : IDictionary<TKey, TValue>
 
-         where TValue : class {
 
-         private readonly Dictionary<TKey, WeakReference> inner;
 
-         private readonly WeakReference gcSentinel = new WeakReference(new object());
 
-         #region Cleanup handling
 
-         private bool IsCleanupNeeded() {
 
-             if (gcSentinel.Target == null) {
 
-                 gcSentinel.Target = new object();
 
-                 return true;
 
-             }
 
-             return false;
 
-         }
 
-         private void CleanAbandonedItems() {
 
-             var keysToRemove = inner.Where(pair => !pair.Value.IsAlive)
 
-                 .Select(pair => pair.Key)
 
-                 .ToList();
 
-             keysToRemove.Apply(key => inner.Remove(key));
 
-         }
 
-         private void CleanIfNeeded() {
 
-             if (IsCleanupNeeded()) {
 
-                 CleanAbandonedItems();
 
-             }
 
-         }
 
-         #endregion
 
-         #region Constructors
 
-         /// <summary>
 
-         /// Initializes a new instance of the <see cref="WeakValueDictionary<TKey, TValue>"/> class that is empty, has the default initial capacity, and uses the default equality comparer for the key type.
 
-         /// </summary>
 
-         public WeakValueDictionary() {
 
-             inner = new Dictionary<TKey, WeakReference>();
 
-         }
 
-         /// <summary>
 
-         /// Initializes a new instance of the <see cref="WeakValueDictionary<TKey, TValue>"/> class that contains elements copied from the specified <see cref="IDictionary<TKey, TValue>"/> and uses the default equality comparer for the key type.
 
-         /// </summary>
 
-         /// <param name="dictionary">The <see cref="IDictionary<TKey, TValue>"/> whose elements are copied to the new <see cref="WeakValueDictionary<TKey, TValue>"/>.</param>
 
-         public WeakValueDictionary(IDictionary<TKey, TValue> dictionary) {
 
-             inner = new Dictionary<TKey, WeakReference>();
 
-             dictionary.Apply(item => inner.Add(item.Key, new WeakReference(item.Value)));
 
-         }
 
-         /// <summary>
 
-         /// Initializes a new instance of the <see cref="WeakValueDictionary<TKey, TValue>"/> class that contains elements copied from the specified <see cref="IDictionary<TKey, TValue>"/> and uses the specified <see cref="IEqualityComparer<T>"/>.
 
-         /// </summary>
 
-         /// <param name="dictionary">The <see cref="IDictionary<TKey, TValue>"/> whose elements are copied to the new <see cref="WeakValueDictionary<TKey, TValue>"/>.</param>
 
-         /// <param name="comparer">The <see cref="IEqualityComparer<T>"/> implementation to use when comparing keys, or null to use the default <see cref="EqualityComparer<T>"/> for the type of the key.</param>
 
-         public WeakValueDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer) {
 
-             inner = new Dictionary<TKey, WeakReference>(comparer);
 
-             dictionary.Apply(item => inner.Add(item.Key, new WeakReference(item.Value)));
 
-         }
 
-         /// <summary>
 
-         /// Initializes a new instance of the <see cref="WeakValueDictionary<TKey, TValue>"/> class that is empty, has the default initial capacity, and uses the specified <see cref="IEqualityComparer<T>"/>.
 
-         /// </summary>
 
-         /// <param name="comparer">The <see cref="IEqualityComparer<T>"/> implementation to use when comparing keys, or null to use the default <see cref="EqualityComparer<T>"/> for the type of the key.</param>
 
-         public WeakValueDictionary(IEqualityComparer<TKey> comparer) {
 
-             inner = new Dictionary<TKey, WeakReference>(comparer);
 
-         }
 
-         /// <summary>
 
-         /// Initializes a new instance of the <see cref="WeakValueDictionary<TKey, TValue>"/> class that is empty, has the specified initial capacity, and uses the default equality comparer for the key type.
 
-         /// </summary>
 
-         /// <param name="capacity">The initial number of elements that the <see cref="WeakValueDictionary<TKey, TValue>"/> can contain.</param>
 
-         public WeakValueDictionary(int capacity) {
 
-             inner = new Dictionary<TKey, WeakReference>(capacity);
 
-         }
 
-         /// <summary>
 
-         /// Initializes a new instance of the <see cref="WeakValueDictionary<TKey, TValue>"/> class that is empty, has the specified initial capacity, and uses the specified <see cref="IEqualityComparer<T>"/>.
 
-         /// </summary>
 
-         /// <param name="capacity">The initial number of elements that the <see cref="WeakValueDictionary<TKey, TValue>"/> can contain.</param>
 
-         /// <param name="comparer">The <see cref="IEqualityComparer<T>"/> implementation to use when comparing keys, or null to use the default <see cref="EqualityComparer<T>"/> for the type of the key.</param>
 
-         public WeakValueDictionary(int capacity, IEqualityComparer<TKey> comparer) {
 
-             inner = new Dictionary<TKey, WeakReference>(capacity, comparer);
 
-         }
 
-         #endregion
 
-         /// <summary>
 
-         /// Returns an enumerator that iterates through the <see cref="WeakValueDictionary<TKey, TValue>"/>.
 
-         /// </summary>
 
-         /// <returns>The enumerator.</returns>
 
-         public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
 
-             CleanIfNeeded();
 
-             var enumerable = inner.Select(pair => new KeyValuePair<TKey, TValue>(pair.Key, (TValue) pair.Value.Target))
 
-                 .Where(pair => pair.Value != null);
 
-             return enumerable.GetEnumerator();
 
-         }
 
-         IEnumerator IEnumerable.GetEnumerator() {
 
-             return GetEnumerator();
 
-         }
 
-         void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) {
 
-             Add(item.Key, item.Value);
 
-         }
 
-         /// <summary>
 
-         /// Removes all keys and values from the <see cref="WeakValueDictionary<TKey, TValue>"/>.
 
-         /// </summary>
 
-         public void Clear() {
 
-             inner.Clear();
 
-         }
 
-         bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) {
 
-             TValue value;
 
-             if (!TryGetValue(item.Key, out value))
 
-                 return false;
 
-             return value == item.Value;
 
-         }
 
-         void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
 
-             if (array == null)
 
-                 throw new ArgumentNullException("array");
 
-             if (arrayIndex < 0 || arrayIndex >= array.Length)
 
-                 throw new ArgumentOutOfRangeException("arrayIndex");
 
-             if ((arrayIndex + Count) > array.Length)
 
-                 throw new ArgumentException(
 
-                     "The number of elements in the source collection is greater than the available space from arrayIndex to the end of the destination array.");
 
-             this.ToArray().CopyTo(array, arrayIndex);
 
-         }
 
-         bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) {
 
-             TValue value;
 
-             if (!TryGetValue(item.Key, out value))
 
-                 return false;
 
-             if (value != item.Value)
 
-                 return false;
 
-             return inner.Remove(item.Key);
 
-         }
 
-         /// <summary>
 
-         /// Gets the number of key/value pairs contained in the <see cref="WeakValueDictionary<TKey, TValue>"/>.
 
-         /// </summary>
 
-         /// <remarks>
 
-         /// Since the items in the dictionary are held by weak reference, the count value
 
-         /// cannot be relied upon to guarantee the number of objects that would be discovered via
 
-         /// enumeration. Treat the Count as an estimate only.
 
-         /// </remarks>
 
-         public int Count {
 
-             get {
 
-                 CleanIfNeeded();
 
-                 return inner.Count;
 
-             }
 
-         }
 
-         bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly {
 
-             get { return false; }
 
-         }
 
-         /// <summary>
 
-         /// Adds the specified key and value to the dictionary.
 
-         /// </summary>
 
-         /// <param name="key">The key of the element to add.</param>
 
-         /// <param name="value">The value of the element to add. The value can be null for reference types.</param>
 
-         public void Add(TKey key, TValue value) {
 
-             CleanIfNeeded();
 
-             inner.Add(key, new WeakReference(value));
 
-         }
 
-         /// <summary>
 
-         /// Determines whether the <see cref="WeakValueDictionary<TKey, TValue>"/> contains the specified key.
 
-         /// </summary>
 
-         /// <param name="key">The key to locate in the <see cref="WeakValueDictionary<TKey, TValue>"/>.</param>
 
-         /// <returns></returns>
 
-         public bool ContainsKey(TKey key) {
 
-             TValue dummy;
 
-             return TryGetValue(key, out dummy);
 
-         }
 
-         /// <summary>
 
-         /// Removes the value with the specified key from the <see cref="WeakValueDictionary<TKey, TValue>"/>.
 
-         /// </summary>
 
-         /// <param name="key">The key of the element to remove.</param>
 
-         /// <returns>true if the element is successfully found and removed; otherwise, false. This method returns false if key is not found in the <see cref="WeakValueDictionary<TKey, TValue>"/>.</returns>
 
-         public bool Remove(TKey key) {
 
-             CleanIfNeeded();
 
-             return inner.Remove(key);
 
-         }
 
-         /// <summary>
 
-         /// Gets the value associated with the specified key.
 
-         /// </summary>
 
-         /// <param name="key">The key of the value to get.</param>
 
-         /// <param name="value">
 
-         /// 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.</param>
 
-         /// <returns>true if the <see cref="WeakValueDictionary<TKey, TValue>"/> contains an element with the specified key; otherwise, false.</returns>
 
-         public bool TryGetValue(TKey key, out TValue value) {
 
-             CleanIfNeeded();
 
-             WeakReference wr;
 
-             if (!inner.TryGetValue(key, out wr)) {
 
-                 value = null;
 
-                 return false;
 
-             }
 
-             var result = (TValue) wr.Target;
 
-             if (result == null) {
 
-                 inner.Remove(key);
 
-                 value = null;
 
-                 return false;
 
-             }
 
-             value = result;
 
-             return true;
 
-         }
 
-         /// <summary>
 
-         /// Gets or sets the value associated with the specified key.
 
-         /// </summary>
 
-         /// <param name="key">The key of the value to get or set.</param>
 
-         /// <returns>
 
-         /// The value associated with the specified key. If the specified key is not found, a get operation throws a <see cref="KeyNotFoundException"/>, 
 
-         /// and a set operation creates a new element with the specified key.
 
-         /// </returns>
 
-         public TValue this[TKey key] {
 
-             get {
 
-                 TValue result;
 
-                 if (!TryGetValue(key, out result))
 
-                     throw new KeyNotFoundException();
 
-                 return result;
 
-             }
 
-             set {
 
-                 CleanIfNeeded();
 
-                 inner[key] = new WeakReference(value);
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Gets a collection containing the keys in the <see cref="WeakValueDictionary<TKey, TValue>"/>.
 
-         /// </summary>
 
-         public ICollection<TKey> Keys {
 
-             get { return inner.Keys; }
 
-         }
 
-         /// <summary>
 
-         /// Gets a collection containing the values in the <see cref="WeakValueDictionary<TKey, TValue>"/>.
 
-         /// </summary>
 
-         public ICollection<TValue> Values {
 
-             get { return new ValueCollection(this); }
 
-         }
 
-         #region Inner Types
 
-         private sealed class ValueCollection : ICollection<TValue> {
 
-             private readonly WeakValueDictionary<TKey, TValue> inner;
 
-             public ValueCollection(WeakValueDictionary<TKey, TValue> dictionary) {
 
-                 inner = dictionary;
 
-             }
 
-             public IEnumerator<TValue> GetEnumerator() {
 
-                 return inner.Select(pair => pair.Value).GetEnumerator();
 
-             }
 
-             IEnumerator IEnumerable.GetEnumerator() {
 
-                 return GetEnumerator();
 
-             }
 
-             void ICollection<TValue>.Add(TValue item) {
 
-                 throw new NotSupportedException();
 
-             }
 
-             void ICollection<TValue>.Clear() {
 
-                 throw new NotSupportedException();
 
-             }
 
-             bool ICollection<TValue>.Contains(TValue item) {
 
-                 return inner.Any(pair => pair.Value == item);
 
-             }
 
-             public void CopyTo(TValue[] array, int arrayIndex) {
 
-                 if (array == null)
 
-                     throw new ArgumentNullException("array");
 
-                 if (arrayIndex < 0 || arrayIndex >= array.Length)
 
-                     throw new ArgumentOutOfRangeException("arrayIndex");
 
-                 if ((arrayIndex + Count) > array.Length)
 
-                     throw new ArgumentException(
 
-                         "The number of elements in the source collection is greater than the available space from arrayIndex to the end of the destination array.");
 
-                 this.ToArray().CopyTo(array, arrayIndex);
 
-             }
 
-             bool ICollection<TValue>.Remove(TValue item) {
 
-                 throw new NotSupportedException();
 
-             }
 
-             public int Count {
 
-                 get { return inner.Count; }
 
-             }
 
-             bool ICollection<TValue>.IsReadOnly {
 
-                 get { return true; }
 
-             }
 
-         }
 
-         #endregion
 
-     }
 
- }
 
 
  |