/* Copyright 2008 The 'A Concurrent Hashtable' development team (http://www.codeplex.com/CH/People/ProjectPeople.aspx) This library is licensed under the GNU Library General Public License (LGPL). You should have received a copy of the license along with the source code. If not, an online copy of the license can be found at http://www.codeplex.com/CH/license. */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using System.Runtime.Serialization; using System.Security; namespace Orvid.Concurrent.Collections { #if !SILVERLIGHT [Serializable] #endif public class WeakKeyDictionary : DictionaryBase, TValue> #if !SILVERLIGHT , ISerializable #endif where TWeakKey1 : class where TWeakKey2 : class where TWeakKey3 : class where TValue : class { sealed class InternalWeakDictionary : InternalWeakDictionaryStrongValueBase< Key, Tuple, TValue, Stacktype > { public InternalWeakDictionary(int concurrencyLevel, int capacity, KeyComparer keyComparer) : base(concurrencyLevel, capacity, keyComparer) { _comparer = keyComparer; MaintenanceWorker.Register(this); } public InternalWeakDictionary(KeyComparer keyComparer) : base(keyComparer) { _comparer = keyComparer; MaintenanceWorker.Register(this); } public KeyComparer _comparer; protected override Key FromExternalKeyToSearchKey(Tuple externalKey) { return new SearchKey().Set(externalKey, _comparer); } protected override Key FromExternalKeyToStorageKey(Tuple externalKey) { return new StorageKey().Set(externalKey, _comparer); } protected override Key FromStackKeyToSearchKey(Stacktype externalKey) { return new SearchKey().Set(externalKey, _comparer); } protected override Key FromStackKeyToStorageKey(Stacktype externalKey) { return new StorageKey().Set(externalKey, _comparer); } protected override bool FromInternalKeyToExternalKey(Key internalKey, out Tuple externalKey) { return internalKey.Get(out externalKey); } protected override bool FromInternalKeyToStackKey(Key internalKey, out Stacktype externalKey) { return internalKey.Get(out externalKey); } } readonly InternalWeakDictionary _internalDictionary; protected override IDictionary, TValue> InternalDictionary { get { return _internalDictionary; } } #if !SILVERLIGHT WeakKeyDictionary(SerializationInfo serializationInfo, StreamingContext streamingContext) { var comparer = (KeyComparer)serializationInfo.GetValue("Comparer", typeof(KeyComparer)); var items = (List, TValue>>)serializationInfo.GetValue("Items", typeof(List, TValue>>)); _internalDictionary = new InternalWeakDictionary(comparer); _internalDictionary.InsertContents(items); } #region ISerializable Members [SecurityCritical] void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("Comparer", _internalDictionary._comparer); info.AddValue("Items", _internalDictionary.GetContents()); } #endregion #endif public WeakKeyDictionary() : this(EqualityComparer.Default, EqualityComparer.Default, EqualityComparer.Default, EqualityComparer.Default) {} public WeakKeyDictionary(IEqualityComparer weakKey1Comparer, IEqualityComparer weakKey2Comparer, IEqualityComparer weakKey3Comparer, IEqualityComparer strongKeyComparer) : this(Enumerable.Empty, TValue>>(), weakKey1Comparer, weakKey2Comparer, weakKey3Comparer, strongKeyComparer) {} public WeakKeyDictionary(IEnumerable, TValue>> collection) : this(collection, EqualityComparer.Default, EqualityComparer.Default, EqualityComparer.Default, EqualityComparer.Default) {} public WeakKeyDictionary(IEnumerable, TValue>> collection, IEqualityComparer weakKey1Comparer, IEqualityComparer weakKey2Comparer, IEqualityComparer weakKey3Comparer, IEqualityComparer strongKeyComparer) { _internalDictionary = new InternalWeakDictionary( new KeyComparer(weakKey1Comparer, weakKey2Comparer, weakKey3Comparer, strongKeyComparer) ) ; _internalDictionary.InsertContents(collection); } public WeakKeyDictionary(int concurrencyLevel, int capacity) : this(concurrencyLevel, capacity, EqualityComparer.Default, EqualityComparer.Default, EqualityComparer.Default, EqualityComparer.Default) {} public WeakKeyDictionary(int concurrencyLevel, IEnumerable, TValue>> collection, IEqualityComparer weakKey1Comparer, IEqualityComparer weakKey2Comparer, IEqualityComparer weakKey3Comparer, IEqualityComparer strongKeyComparer) { var contentsList = collection.ToList(); _internalDictionary = new InternalWeakDictionary( concurrencyLevel, contentsList.Count, new KeyComparer(weakKey1Comparer, weakKey2Comparer, weakKey3Comparer, strongKeyComparer) ) ; _internalDictionary.InsertContents(contentsList); } public WeakKeyDictionary(int concurrencyLevel, int capacity, IEqualityComparer weakKey1Comparer, IEqualityComparer weakKey2Comparer, IEqualityComparer weakKey3Comparer, IEqualityComparer strongKeyComparer) { _internalDictionary = new InternalWeakDictionary( concurrencyLevel, capacity, new KeyComparer(weakKey1Comparer, weakKey2Comparer, weakKey3Comparer, strongKeyComparer) ) ; } public bool ContainsKey(TWeakKey1 weakKey1, TWeakKey2 weakKey2, TWeakKey3 weakKey3, TStrongKey strongKey) { return _internalDictionary.ContainsKey(Stacktype.Create(weakKey1, weakKey2, weakKey3, strongKey)); } public bool TryGetValue(TWeakKey1 weakKey1, TWeakKey2 weakKey2, TWeakKey3 weakKey3, TStrongKey strongKey, out TValue value) { return _internalDictionary.TryGetValue(Stacktype.Create(weakKey1, weakKey2, weakKey3, strongKey), out value); } public TValue this[TWeakKey1 weakKey1, TWeakKey2 weakKey2, TWeakKey3 weakKey3, TStrongKey strongKey] { get { return _internalDictionary.GetItem(Stacktype.Create(weakKey1, weakKey2, weakKey3, strongKey)); } set { _internalDictionary.SetItem(Stacktype.Create(weakKey1, weakKey2, weakKey3, strongKey), value); } } public bool IsEmpty { get { return _internalDictionary.IsEmpty; } } public TValue AddOrUpdate(TWeakKey1 weakKey1, TWeakKey2 weakKey2, TWeakKey3 weakKey3, TStrongKey strongKey, Func addValueFactory, Func updateValueFactory) { if (null == addValueFactory) throw new ArgumentNullException("addValueFactory"); if (null == updateValueFactory) throw new ArgumentNullException("updateValueFactory"); return _internalDictionary.AddOrUpdate( Stacktype.Create(weakKey1, weakKey2, weakKey3, strongKey), hr => addValueFactory(hr.Item1, hr.Item2, hr.Item3, hr.Item4), (hr, v) => updateValueFactory(hr.Item1, hr.Item2, hr.Item3, hr.Item4, v) ) ; } public TValue AddOrUpdate(TWeakKey1 weakKey1, TWeakKey2 weakKey2, TWeakKey3 weakKey3, TStrongKey strongKey, TValue addValue, Func updateValueFactory) { if (null == updateValueFactory) throw new ArgumentNullException("updateValueFactory"); return _internalDictionary.AddOrUpdate( Stacktype.Create(weakKey1, weakKey2, weakKey3, strongKey), addValue, (hr, v) => updateValueFactory(hr.Item1, hr.Item2, hr.Item3, hr.Item4, v) ) ; } public TValue GetOrAdd(TWeakKey1 weakKey1, TWeakKey2 weakKey2, TWeakKey3 weakKey3, TStrongKey strongKey, TValue value) { return _internalDictionary.GetOrAdd(Stacktype.Create(weakKey1, weakKey2, weakKey3, strongKey), value); } public TValue GetOrAdd(TWeakKey1 weakKey1, TWeakKey2 weakKey2, TWeakKey3 weakKey3, TStrongKey strongKey, Func valueFactory) { if (null == valueFactory) throw new ArgumentNullException("valueFactory"); return _internalDictionary.GetOrAdd(Stacktype.Create(weakKey1, weakKey2, weakKey3, strongKey), hr => valueFactory(hr.Item1, hr.Item2, hr.Item3, hr.Item4)); } public KeyValuePair, TValue>[] ToArray() { return _internalDictionary.ToArray(); } public bool TryAdd(TWeakKey1 weakKey1, TWeakKey2 weakKey2, TWeakKey3 weakKey3, TStrongKey strongKey, TValue value) { return _internalDictionary.TryAdd(Stacktype.Create(weakKey1, weakKey2, weakKey3, strongKey), value); } public bool TryRemove(TWeakKey1 weakKey1, TWeakKey2 weakKey2, TWeakKey3 weakKey3, TStrongKey strongKey, out TValue value) { return _internalDictionary.TryRemove(Stacktype.Create(weakKey1, weakKey2, weakKey3, strongKey), out value); } public bool TryUpdate(TWeakKey1 weakKey1, TWeakKey2 weakKey2, TWeakKey3 weakKey3, TStrongKey strongKey, TValue newValue, TValue comparisonValue) { return _internalDictionary.TryUpdate(Stacktype.Create(weakKey1, weakKey2, weakKey3, strongKey), newValue, comparisonValue ); } } }