1 // -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
5 // This code comes from the Managed Extension Frameworks:
6 // http://mef.codeplex.com
8 // And is licensed under the MS-PL license
11 // "I think our table is weak, but does not do proper compacting"
14 #if NET_4_0 || BOOTSTRAP_NET_4_0 || MOONLIGHT
16 using System.Collections;
17 using System.Collections.Generic;
20 namespace System.Runtime.CompilerServices
23 // This is a broken implementation of ConditionalWeakTable that allows us
24 // to compile and work on versions of .Net eariler then 4.0. This class is
25 // broken when there are circular dependencies between keys and values, which
26 // can only be fixed by using some specific CLR 4.0 features.
27 // For code samples of the broken behavior see ConditionalWeakTableTests.cs.
28 public class ConditionalWeakTable<TKey, TValue>
32 private readonly Dictionary<object, TValue> _table;
33 private int _capacity = 4;
35 public ConditionalWeakTable()
37 this._table = new Dictionary<object, TValue>();
40 public void Add(TKey key, TValue value)
42 CleanupDeadReferences();
43 this._table.Add(CreateWeakKey(key), value);
46 public bool Remove(TKey key)
48 return this._table.Remove(key);
51 public bool TryGetValue(TKey key, out TValue value)
53 return this._table.TryGetValue(key, out value);
56 private void CleanupDeadReferences()
58 if (this._table.Count < _capacity)
63 ArrayList deadKeys = new ArrayList ();
64 foreach (var weakRef in _table.Keys){
65 if (!((EquivalentWeakReference)weakRef).IsAlive)
66 deadKeys.Add (weakRef);
69 foreach (var deadKey in deadKeys)
71 this._table.Remove(deadKey);
74 if (this._table.Count >= _capacity)
80 private static object CreateWeakKey(TKey key)
82 return new EquivalentWeakReference(key);
85 private class EquivalentWeakReference
87 private readonly WeakReference _weakReference;
88 private readonly int _hashCode;
90 public EquivalentWeakReference(object obj)
92 this._hashCode = obj.GetHashCode();
93 this._weakReference = new WeakReference(obj);
100 return this._weakReference.IsAlive;
104 public override bool Equals(object obj)
106 EquivalentWeakReference weakRef = obj as EquivalentWeakReference;
110 obj = weakRef._weakReference.Target;
115 return base.Equals(weakRef);
118 return object.Equals(this._weakReference.Target, obj);
121 public override int GetHashCode()
123 return this._hashCode;