| File: FrameworkFork\System.ServiceModel\System\ServiceModel\SynchronizedKeyedCollection.cs | Web Access |
| Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Runtime; using System.Runtime.InteropServices; using System.ServiceModel; namespace System.Collections.Generic { [ComVisible(false)] public abstract class SynchronizedKeyedCollection<K, T> : SynchronizedCollection<T> { private const int defaultThreshold = 0; private IEqualityComparer<K> _comparer; private Dictionary<K, T> _dictionary; private int _keyCount; private int _threshold; protected SynchronizedKeyedCollection() { _comparer = EqualityComparer<K>.Default; _threshold = int.MaxValue; } protected SynchronizedKeyedCollection(object syncRoot) : base(syncRoot) { _comparer = EqualityComparer<K>.Default; _threshold = int.MaxValue; } protected SynchronizedKeyedCollection(object syncRoot, IEqualityComparer<K> comparer) : base(syncRoot) { if (comparer == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("comparer")); _comparer = comparer; _threshold = int.MaxValue; } protected SynchronizedKeyedCollection(object syncRoot, IEqualityComparer<K> comparer, int dictionaryCreationThreshold) : base(syncRoot) { if (comparer == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("comparer")); if (dictionaryCreationThreshold < -1) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("dictionaryCreationThreshold", dictionaryCreationThreshold, string.Format(SRServiceModel.ValueMustBeInRange, -1, int.MaxValue))); else if (dictionaryCreationThreshold == -1) _threshold = int.MaxValue; else _threshold = dictionaryCreationThreshold; _comparer = comparer; } public T this[K key] { get { if (key == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("key")); lock (this.SyncRoot) { if (_dictionary != null) return _dictionary[key]; for (int i = 0; i < this.Items.Count; i++) { T item = this.Items[i]; if (_comparer.Equals(key, this.GetKeyForItem(item))) return item; } throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new KeyNotFoundException()); } } } protected IDictionary<K, T> Dictionary { get { return _dictionary; } } private void AddKey(K key, T item) { if (_dictionary != null) _dictionary.Add(key, item); else if (_keyCount == _threshold) { this.CreateDictionary(); _dictionary.Add(key, item); } else { if (this.Contains(key)) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SRServiceModel.CannotAddTwoItemsWithTheSameKeyToSynchronizedKeyedCollection0)); _keyCount++; } } protected void ChangeItemKey(T item, K newKey) { // check if the item exists in the collection if (!this.ContainsItem(item)) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SRServiceModel.ItemDoesNotExistInSynchronizedKeyedCollection0)); K oldKey = this.GetKeyForItem(item); if (!_comparer.Equals(newKey, oldKey)) { if (newKey != null) this.AddKey(newKey, item); if (oldKey != null) this.RemoveKey(oldKey); } } protected override void ClearItems() { base.ClearItems(); if (_dictionary != null) _dictionary.Clear(); _keyCount = 0; } public bool Contains(K key) { if (key == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("key")); lock (this.SyncRoot) { if (_dictionary != null) return _dictionary.ContainsKey(key); if (key != null) { for (int i = 0; i < Items.Count; i++) { T item = Items[i]; if (_comparer.Equals(key, GetKeyForItem(item))) return true; } } return false; } } private bool ContainsItem(T item) { K key; if ((_dictionary == null) || ((key = GetKeyForItem(item)) == null)) return Items.Contains(item); T itemInDict; if (_dictionary.TryGetValue(key, out itemInDict)) return EqualityComparer<T>.Default.Equals(item, itemInDict); return false; } private void CreateDictionary() { _dictionary = new Dictionary<K, T>(_comparer); foreach (T item in Items) { K key = GetKeyForItem(item); if (key != null) _dictionary.Add(key, item); } } protected abstract K GetKeyForItem(T item); protected override void InsertItem(int index, T item) { K key = this.GetKeyForItem(item); if (key != null) this.AddKey(key, item); base.InsertItem(index, item); } public bool Remove(K key) { if (key == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("key")); lock (this.SyncRoot) { if (_dictionary != null) { if (_dictionary.ContainsKey(key)) return this.Remove(_dictionary[key]); else return false; } else { for (int i = 0; i < Items.Count; i++) { if (_comparer.Equals(key, GetKeyForItem(Items[i]))) { this.RemoveItem(i); return true; } } return false; } } } protected override void RemoveItem(int index) { K key = this.GetKeyForItem(this.Items[index]); if (key != null) this.RemoveKey(key); base.RemoveItem(index); } private void RemoveKey(K key) { if (!(key != null)) { Fx.Assert("key shouldn't be null!"); throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("key"); } if (_dictionary != null) _dictionary.Remove(key); else _keyCount--; } protected override void SetItem(int index, T item) { K newKey = this.GetKeyForItem(item); K oldKey = this.GetKeyForItem(this.Items[index]); if (_comparer.Equals(newKey, oldKey)) { if ((newKey != null) && (_dictionary != null)) _dictionary[newKey] = item; } else { if (newKey != null) this.AddKey(newKey, item); if (oldKey != null) this.RemoveKey(oldKey); } base.SetItem(index, item); } } }