/* 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 WeakValueDictionary : DictionaryBase #if !SILVERLIGHT , ISerializable #endif where TValue : class { class InternalWeakDictionary : InternalWeakDictionaryWeakValueBase< StrongKey, TStrongKey, TValue, Stacktype > { public InternalWeakDictionary(int concurrencyLevel, int capacity, KeyComparer keyComparer) : base(concurrencyLevel, capacity, keyComparer) { _comparer = keyComparer; } public InternalWeakDictionary(KeyComparer keyComparer) : base(keyComparer) { _comparer = keyComparer; } public KeyComparer _comparer; protected override StrongKey FromExternalKeyToSearchKey(TStrongKey externalKey) { return new StrongKey() { _element = externalKey }; } protected override StrongKey FromExternalKeyToStorageKey(TStrongKey externalKey) { return new StrongKey() { _element = externalKey }; } protected override StrongKey FromStackKeyToSearchKey(Stacktype externalKey) { return new StrongKey() { _element = externalKey.Item1 }; } protected override StrongKey FromStackKeyToStorageKey(Stacktype externalKey) { return new StrongKey() { _element = externalKey.Item1 }; } protected override bool FromInternalKeyToExternalKey(StrongKey internalKey, out TStrongKey externalKey) { externalKey = internalKey._element; return true; } protected override bool FromInternalKeyToStackKey(StrongKey internalKey, out Stacktype externalKey) { externalKey = Stacktype.Create(internalKey._element); return true; } } readonly InternalWeakDictionary _internalDictionary; protected override IDictionary InternalDictionary { get { return _internalDictionary; } } #if !SILVERLIGHT WeakValueDictionary(SerializationInfo serializationInfo, StreamingContext streamingContext) { var comparer = (KeyComparer)serializationInfo.GetValue("Comparer", typeof(KeyComparer)); var items = (List>)serializationInfo.GetValue("Items", typeof(List>)); _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 WeakValueDictionary() : this(EqualityComparer.Default) {} public WeakValueDictionary(IEqualityComparer strongKeyComparer) : this(Enumerable.Empty>(), strongKeyComparer) {} public WeakValueDictionary(IEnumerable> collection) : this(collection, EqualityComparer.Default) {} public WeakValueDictionary(IEnumerable> collection, IEqualityComparer strongKeyComparer) { _internalDictionary = new InternalWeakDictionary( new KeyComparer(strongKeyComparer) ) ; _internalDictionary.InsertContents(collection); } public WeakValueDictionary(int concurrencyLevel, int capacity) : this(concurrencyLevel, capacity, EqualityComparer.Default) {} public WeakValueDictionary(int concurrencyLevel, IEnumerable> collection, IEqualityComparer strongKeyComparer) { var contentsList = collection.ToList(); _internalDictionary = new InternalWeakDictionary( concurrencyLevel, contentsList.Count, new KeyComparer(strongKeyComparer) ) ; _internalDictionary.InsertContents(contentsList); } public WeakValueDictionary(int concurrencyLevel, int capacity, IEqualityComparer strongKeyComparer) { _internalDictionary = new InternalWeakDictionary( concurrencyLevel, capacity, new KeyComparer(strongKeyComparer) ) ; } public bool ContainsKey(TStrongKey strongKey) { return _internalDictionary.ContainsKey(Stacktype.Create(strongKey)); } public bool TryGetValue(TStrongKey strongKey, out TValue value) { return _internalDictionary.TryGetValue(Stacktype.Create(strongKey), out value); } public TValue this[TStrongKey strongKey] { get { return _internalDictionary.GetItem(Stacktype.Create(strongKey)); } set { _internalDictionary.SetItem(Stacktype.Create(strongKey), value); } } public bool IsEmpty { get { return _internalDictionary.IsEmpty; } } public TValue AddOrUpdate(TStrongKey strongKey, Func addValueFactory, Func updateValueFactory) { return _internalDictionary.AddOrUpdate( Stacktype.Create(strongKey), ht => addValueFactory(ht.Item1), (ht, v) => updateValueFactory(ht.Item1, v) ) ; } public TValue AddOrUpdate(TStrongKey strongKey, TValue addValue, Func updateValueFactory) { return _internalDictionary.AddOrUpdate( Stacktype.Create(strongKey), addValue, (ht, v) => updateValueFactory(ht.Item1, v) ) ; } public TValue GetOrAdd(TStrongKey strongKey, TValue value) { return _internalDictionary.GetOrAdd(Stacktype.Create(strongKey), value); } public TValue GetOrAdd(TStrongKey strongKey, Func valueFactory) { if (null == valueFactory) throw new ArgumentNullException("valueFactory"); return _internalDictionary.GetOrAdd(Stacktype.Create(strongKey), ht => valueFactory(ht.Item1)); } public KeyValuePair[] ToArray() { return _internalDictionary.ToArray(); } public bool TryAdd(TStrongKey strongKey, TValue value) { return _internalDictionary.TryAdd(Stacktype.Create(strongKey), value); } public bool TryRemove(TStrongKey strongKey, out TValue value) { return _internalDictionary.TryRemove(Stacktype.Create(strongKey), out value); } public bool TryUpdate(TStrongKey strongKey, TValue newValue, TValue comparisonValue) { return _internalDictionary.TryUpdate(Stacktype.Create(strongKey), newValue, comparisonValue); } } }