C:\Devel\PlayniteDiagTool\PlayniteDiagTool\bin\Debug\temp\PlayniteSDK\Collections\ObservableConcurrentDictionary.cs c:\Devel\Playnite\source\PlayniteSDK\Collections\ObservableConcurrentDictionary.cs
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// //
//  Copyright (c) Microsoft Corporation.  All rights reserved. //  Copyright (c) Microsoft Corporation.  All rights reserved.
// //
//  File: ObservableConcurrentDictionary.cs //  File: ObservableConcurrentDictionary.cs
// //
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
   
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.Threading; using System.Threading;
using System.Diagnostics; using System.Diagnostics;
   
namespace System.Collections.Concurrent namespace System.Collections.Concurrent
{ {
   /// <summary>    /// <summary>
   /// Provides a thread-safe dictionary for use with data binding.    /// Provides a thread-safe dictionary for use with data binding.
   /// </summary>    /// </summary>
   /// <typeparam name="TKey">Specifies the type of the keys in this collection.</typeparam>    /// <typeparam name="TKey">Specifies the type of the keys in this collection.</typeparam>
   /// <typeparam name="TValue">Specifies the type of the values in this collection.</typeparam>    /// <typeparam name="TValue">Specifies the type of the values in this collection.</typeparam>
   [DebuggerDisplay("Count={Count}")]    [DebuggerDisplay("Count={Count}")]
   public class ObservableConcurrentDictionary<TKey, TValue> :    public class ObservableConcurrentDictionary<TKey, TValue> :
       ICollection<KeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue>,        ICollection<KeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue>,
       INotifyCollectionChanged, INotifyPropertyChanged        INotifyCollectionChanged, INotifyPropertyChanged
   {    {
       private readonly SynchronizationContext _context;        private readonly SynchronizationContext _context;
       private readonly ConcurrentDictionary<TKey, TValue> _dictionary;        private readonly ConcurrentDictionary<TKey, TValue> _dictionary;
   
       /// <summary>        /// <summary>
       /// Initializes an instance of the ObservableConcurrentDictionary class.        /// Initializes an instance of the ObservableConcurrentDictionary class.
       /// </summary>        /// </summary>
       public ObservableConcurrentDictionary()        public ObservableConcurrentDictionary()
       {        {
           _context = AsyncOperationManager.SynchronizationContext;            _context = AsyncOperationManager.SynchronizationContext;
           _dictionary = new ConcurrentDictionary<TKey, TValue>();            _dictionary = new ConcurrentDictionary<TKey, TValue>();
       }        }
   
       /// <summary>Event raised when the collection changes.</summary>        /// <summary>Event raised when the collection changes.</summary>
       public event NotifyCollectionChangedEventHandler CollectionChanged;        public event NotifyCollectionChangedEventHandler CollectionChanged;
.        /// <summary>Event raised when a property on the collection changes.</summary>        /// <summary>Event raised when a property in the collection changes.</summary>
       public event PropertyChangedEventHandler PropertyChanged;        public event PropertyChangedEventHandler PropertyChanged;
   
       /// <summary>        /// <summary>
       /// Notifies observers of CollectionChanged or PropertyChanged of an update to the dictionary.        /// Notifies observers of CollectionChanged or PropertyChanged of an update to the dictionary.
       /// </summary>        /// </summary>
       private void NotifyObserversOfChange()        private void NotifyObserversOfChange()
       {        {
           var collectionHandler = CollectionChanged;            var collectionHandler = CollectionChanged;
           var propertyHandler = PropertyChanged;            var propertyHandler = PropertyChanged;
           if (collectionHandler != null || propertyHandler != null)            if (collectionHandler != null || propertyHandler != null)
           {            {
               _context.Send(s =>                _context.Send(s =>
               {                {
                   collectionHandler?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));                    collectionHandler?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
   
                   if (propertyHandler != null)                    if (propertyHandler != null)
                   {                    {
                       propertyHandler(this, new PropertyChangedEventArgs("Count"));                        propertyHandler(this, new PropertyChangedEventArgs("Count"));
                       propertyHandler(this, new PropertyChangedEventArgs("Keys"));                        propertyHandler(this, new PropertyChangedEventArgs("Keys"));
                       propertyHandler(this, new PropertyChangedEventArgs("Values"));                        propertyHandler(this, new PropertyChangedEventArgs("Values"));
                   }                    }
               }, null);                }, null);
           }            }
       }        }
   
       /// <summary>Attempts to add an item to the dictionary, notifying observers of any changes.</summary>        /// <summary>Attempts to add an item to the dictionary, notifying observers of any changes.</summary>
       /// <param name="item">The item to be added.</param>        /// <param name="item">The item to be added.</param>
       /// <returns>Whether the add was successful.</returns>        /// <returns>Whether the add was successful.</returns>
       private bool TryAddWithNotification(KeyValuePair<TKey, TValue> item)        private bool TryAddWithNotification(KeyValuePair<TKey, TValue> item)
       {        {
           return TryAddWithNotification(item.Key, item.Value);            return TryAddWithNotification(item.Key, item.Value);
       }        }
   
       /// <summary>Attempts to add an item to the dictionary, notifying observers of any changes.</summary>        /// <summary>Attempts to add an item to the dictionary, notifying observers of any changes.</summary>
       /// <param name="key">The key of the item to be added.</param>        /// <param name="key">The key of the item to be added.</param>
       /// <param name="value">The value of the item to be added.</param>        /// <param name="value">The value of the item to be added.</param>
       /// <returns>Whether the add was successful.</returns>        /// <returns>Whether the add was successful.</returns>
       private bool TryAddWithNotification(TKey key, TValue value)        private bool TryAddWithNotification(TKey key, TValue value)
       {        {
           bool result = _dictionary.TryAdd(key, value);            bool result = _dictionary.TryAdd(key, value);
           if (result)            if (result)
               NotifyObserversOfChange();                NotifyObserversOfChange();
           return result;            return result;
       }        }
   
       /// <summary>Attempts to remove an item from the dictionary, notifying observers of any changes.</summary>        /// <summary>Attempts to remove an item from the dictionary, notifying observers of any changes.</summary>
       /// <param name="key">The key of the item to be removed.</param>        /// <param name="key">The key of the item to be removed.</param>
       /// <param name="value">The value of the item removed.</param>        /// <param name="value">The value of the item removed.</param>
       /// <returns>Whether the removal was successful.</returns>        /// <returns>Whether the removal was successful.</returns>
       private bool TryRemoveWithNotification(TKey key, out TValue value)        private bool TryRemoveWithNotification(TKey key, out TValue value)
       {        {
           bool result = _dictionary.TryRemove(key, out value);            bool result = _dictionary.TryRemove(key, out value);
           if (result)            if (result)
               NotifyObserversOfChange();                NotifyObserversOfChange();
           return result;            return result;
       }        }
   
       /// <summary>Attempts to add or update an item in the dictionary, notifying observers of any changes.</summary>        /// <summary>Attempts to add or update an item in the dictionary, notifying observers of any changes.</summary>
       /// <param name="key">The key of the item to be updated.</param>        /// <param name="key">The key of the item to be updated.</param>
       /// <param name="value">The new value to set for the item.</param>        /// <param name="value">The new value to set for the item.</param>
       /// <returns>Whether the update was successful.</returns>        /// <returns>Whether the update was successful.</returns>
       private void UpdateWithNotification(TKey key, TValue value)        private void UpdateWithNotification(TKey key, TValue value)
       {        {
           _dictionary[key] = value;            _dictionary[key] = value;
           NotifyObserversOfChange();            NotifyObserversOfChange();
       }        }
   
       #region ICollection<KeyValuePair<TKey,TValue>> Members        #region ICollection<KeyValuePair<TKey,TValue>> Members
       void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
       {        {
           TryAddWithNotification(item);            TryAddWithNotification(item);
       }        }
   
       void ICollection<KeyValuePair<TKey, TValue>>.Clear()        void ICollection<KeyValuePair<TKey, TValue>>.Clear()
       {        {
           ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Clear();            ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Clear();
           NotifyObserversOfChange();            NotifyObserversOfChange();
       }        }
   
       bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
       {        {
           return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Contains(item);            return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Contains(item);
       }        }
   
       void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
       {        {
           ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).CopyTo(array, arrayIndex);            ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).CopyTo(array, arrayIndex);
       }        }
   
       int ICollection<KeyValuePair<TKey, TValue>>.Count        int ICollection<KeyValuePair<TKey, TValue>>.Count
       {        {
           get            get
           {            {
               return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Count;                return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Count;
           }            }
       }        }
   
       bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly        bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
       {        {
           get            get
           {            {
               return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).IsReadOnly;                return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).IsReadOnly;
           }            }
       }        }
   
       bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
       {        {
           return TryRemoveWithNotification(item.Key, out TValue temp);            return TryRemoveWithNotification(item.Key, out TValue temp);
       }        }
       #endregion        #endregion
   
       #region IEnumerable<KeyValuePair<TKey,TValue>> Members        #region IEnumerable<KeyValuePair<TKey,TValue>> Members
       IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
       {        {
           return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).GetEnumerator();            return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).GetEnumerator();
       }        }
   
       IEnumerator IEnumerable.GetEnumerator()        IEnumerator IEnumerable.GetEnumerator()
       {        {
           return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).GetEnumerator();            return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).GetEnumerator();
       }        }
       #endregion        #endregion
   
       #region IDictionary<TKey,TValue> Members        #region IDictionary<TKey,TValue> Members
       /// <summary>        /// <summary>
       ///        ///
       /// </summary>        /// </summary>
       /// <param name="key"></param>        /// <param name="key"></param>
       /// <param name="value"></param>        /// <param name="value"></param>
       public void Add(TKey key, TValue value)        public void Add(TKey key, TValue value)
       {        {
           TryAddWithNotification(key, value);            TryAddWithNotification(key, value);
       }        }
   
       /// <summary>        /// <summary>
       ///        ///
       /// </summary>        /// </summary>
       /// <param name="key"></param>        /// <param name="key"></param>
       /// <returns></returns>        /// <returns></returns>
       public bool ContainsKey(TKey key)        public bool ContainsKey(TKey key)
       {        {
           return _dictionary.ContainsKey(key);            return _dictionary.ContainsKey(key);
       }        }
   
       /// <summary>        /// <summary>
       ///        ///
       /// </summary>        /// </summary>
       public ICollection<TKey> Keys        public ICollection<TKey> Keys
       {        {
           get            get
           {            {
               return _dictionary.Keys;                return _dictionary.Keys;
           }            }
       }        }
   
       /// <summary>        /// <summary>
       ///        ///
       /// </summary>        /// </summary>
       /// <param name="key"></param>        /// <param name="key"></param>
       /// <returns></returns>        /// <returns></returns>
       public bool Remove(TKey key)        public bool Remove(TKey key)
       {        {
           return TryRemoveWithNotification(key, out TValue temp);            return TryRemoveWithNotification(key, out TValue temp);
       }        }
   
       /// <summary>        /// <summary>
       ///        ///
       /// </summary>        /// </summary>
       /// <param name="key"></param>        /// <param name="key"></param>
       /// <param name="value"></param>        /// <param name="value"></param>
       /// <returns></returns>        /// <returns></returns>
       public bool TryGetValue(TKey key, out TValue value)        public bool TryGetValue(TKey key, out TValue value)
       {        {
           return _dictionary.TryGetValue(key, out value);            return _dictionary.TryGetValue(key, out value);
       }        }
   
       /// <summary>        /// <summary>
       ///        ///
       /// </summary>        /// </summary>
       public ICollection<TValue> Values        public ICollection<TValue> Values
       {        {
           get            get
           {            {
               return _dictionary.Values;                return _dictionary.Values;
           }            }
       }        }
   
       /// <summary>        /// <summary>
       ///        ///
       /// </summary>        /// </summary>
       /// <param name="key"></param>        /// <param name="key"></param>
       /// <returns></returns>        /// <returns></returns>
       public TValue this[TKey key]        public TValue this[TKey key]
       {        {
           get            get
           {            {
               return _dictionary[key];                return _dictionary[key];
           }            }
           set            set
           {            {
               UpdateWithNotification(key, value);                UpdateWithNotification(key, value);
           }            }
       }        }
       #endregion        #endregion
   }    }
} }