/// <summary> /// Returns an enumerator that iterates through the collection. /// </summary> /// <returns> /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection. /// </returns> /// <filterpriority>1</filterpriority> public IEnumerator <TValue> GetEnumerator() { List <Guid> deadGuids = new List <Guid>(); foreach (KeyValuePair <Guid, WeakReference <TValue> > kvp in _dictionary) { Debug.Assert(kvp.Value != null); TValue target; if (!kvp.Value.TryGetTarget(out target)) { deadGuids.Add(kvp.Key); } else { yield return(target); } } foreach (Guid guid in deadGuids) { WeakReference <TValue> weakReference; if (!_dictionary.TryRemove(guid, out weakReference) || !_parent._observable) { continue; } ObservableWeakReference <TValue> owf = weakReference as ObservableWeakReference <TValue>; if (owf != null) { owf.Dispose(); } } }
/// <summary> /// Register the finalize event where appropriate. /// </summary> /// <param name="key">The key.</param> /// <param name="weakReference">The weak reference.</param> private void RegisterFinalize([NotNull] TKey key, [CanBeNull] WeakReference <TValue> weakReference) { if (!_observable || (weakReference == null)) { return; } ObservableWeakReference <TValue> owf = weakReference as ObservableWeakReference <TValue>; if (owf == null) { return; } owf.Finalized += (s, e) => { WeakReference <TValue> oldwr; if (_dictionary.TryRemove(key, out oldwr) && (oldwr != weakReference)) { // If we removed something else, add it back! _dictionary.TryAdd(key, oldwr); } owf.Dispose(); }; }
/// <summary> /// Removes the specified value from the group. /// </summary> /// <param name="value">The value to remove.</param> /// <returns> /// Returns <see langword="true"/> if the value was successfully removed; otherwise returns <see langword="false"/>. /// </returns> public bool Remove(TValue value) { // Scan dictionary looking for dead elements List <Guid> deadGuids = new List <Guid>(); bool found = false; foreach (KeyValuePair <Guid, WeakReference <TValue> > kvp in _dictionary) { Debug.Assert(kvp.Value != null); TValue v; if (!kvp.Value.TryGetTarget(out v)) { deadGuids.Add(kvp.Key); } if (!_parent._valueComparer.Equals(v, value)) { continue; } deadGuids.Add(kvp.Key); found = true; break; } foreach (Guid guid in deadGuids) { WeakReference <TValue> weakReference; if (!_dictionary.TryRemove(guid, out weakReference) || (weakReference == null)) { continue; } ObservableWeakReference <TValue> owf = weakReference as ObservableWeakReference <TValue>; if (owf != null) { owf.Dispose(); } } // If we're down to one remove grouping. if (_dictionary.Count < 1) { WeakGrouping weakGrouping; _parent._dictionary.TryRemove(Key, out weakGrouping); } return(found); }
/// <summary> /// Wraps the specified value in a weak reference. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> /// <param name="register">If set to <see langword="true"/> registers the finalize event immediately.</param> /// <returns>The wrapped value.</returns> private WeakReference <TValue> Wrap([NotNull] TKey key, [CanBeNull] TValue value, bool register = true) { if (value == null) { return(null); } if (!_observable) { return(new WeakReference <TValue>(value, _allowResurrection)); } ObservableWeakReference <TValue> owf = new ObservableWeakReference <TValue>(value, _allowResurrection); if (register) { RegisterFinalize(key, owf); } return(owf); }
/// <summary> /// Adds the specified value to the group. /// </summary> /// <param name="value">The value to add.</param> /// <returns>The new <paramref name="value"/> added to the group.</returns> public WeakGrouping Add([NotNull] TValue value) { Guid guid = Guid.NewGuid(); WeakReference <TValue> weakReference; if (_parent._observable) { ObservableWeakReference <TValue> owf = new ObservableWeakReference <TValue>( value, _parent._allowResurrection); owf.Finalized += (s, e) => { WeakReference <TValue> removedValue; _dictionary.TryRemove(guid, out removedValue); owf.Dispose(); }; weakReference = owf; } else { weakReference = new WeakReference <TValue>(value, _parent._allowResurrection); } _dictionary.AddOrUpdate( guid, g => weakReference, (g, w) => { if ((_parent._observable) && (w != null)) { ObservableWeakReference <TValue> o = w as ObservableWeakReference <TValue>; if (o != null) { o.Dispose(); } } return(weakReference); }); return(this); }