/// <summary> /// Registers an assembly to extract compatible functions from. /// </summary> /// <param name="assembly">The assembly to register.</param> public void RegisterFunctionsAssembly(Assembly assembly) { _ = Requires.NotNull( assembly, nameof(assembly)); ThrowIfCurrentObjectDisposed(); using ReadWriteSynchronizationLocker innerLocker = ReadWriteLock(); if (isInitialized) { throw new InvalidOperationException( "Initialization has already completed, so you cannot register any more assemblies for this service."); } if (assembliesToRegister.Contains(assembly)) { return; } innerLocker.Upgrade(); assembliesToRegister.Add(assembly); }
/// <summary> /// Removes an item at the specified index. /// </summary> /// <param name="index">The index at which to remove an item from.</param> public override void RemoveAt(int index) { this.RequiresNotDisposed(); T item; using (ReadWriteSynchronizationLocker lockContext = this.ReadWriteLock()) { if (index >= this.InternalContainer.Count) { return; } lockContext.Upgrade(); item = this.InternalContainer[index]; this.IncreaseIgnoreMustResetCounter(); this.InternalContainer.RemoveAt(index); this.PushUndoLevel(new RemoveUndoLevel <T> { Index = index, RemovedItem = item }); } this.RaiseCollectionChangedRemove( item, index); this.RaisePropertyChanged(nameof(this.Count)); this.ContentsMayHaveChanged(); }
/// <summary> /// Removes an item at the specified index. /// </summary> /// <param name="index">The index at which to remove an item from.</param> public override void RemoveAt(int index) { ThrowIfCurrentObjectDisposed(); T item; using (ReadWriteSynchronizationLocker lockContext = ReadWriteLock()) { if (index >= InternalListContainer.Count) { return; } lockContext.Upgrade(); item = InternalListContainer[index]; IncreaseIgnoreMustResetCounter(); InternalListContainer.RemoveAt(index); PushUndoLevel( new RemoveStateChange <T>( index, item)); } RaiseCollectionChangedRemove( item, index); RaisePropertyChanged(nameof(Count)); ContentsMayHaveChanged(); }
/// <summary> /// Attempts to de-queue an item and to remove it from queue. /// </summary> /// <param name="item">The item that has been de-queued, default if unsuccessful.</param> /// <returns> /// <see langword="true" /> if an item is de-queued successfully, <see langword="false" /> otherwise, or if the /// queue is empty. /// </returns> public bool TryDequeue(out T item) { this.RequiresNotDisposed(); using (ReadWriteSynchronizationLocker locker = this.ReadWriteLock()) { var adapter = (QueueCollectionAdapter <T>) this.InternalContainer; if (adapter.Count == 0) { item = default; return(false); } locker.Upgrade(); item = adapter.Dequeue(); this.PushUndoLevel(new DequeueUndoLevel <T> { DequeuedItem = item }); } this.RaisePropertyChanged(nameof(this.Count)); this.RaisePropertyChanged(Constants.ItemsName); this.RaiseCollectionChangedRemove( item, 0); return(true); }
/// <summary> /// Removes an item at the specified index. /// </summary> /// <param name="index">The index at which to remove an item from.</param> public virtual void RemoveAt(int index) { // PRECONDITIONS // Current object not disposed ThrowIfCurrentObjectDisposed(); // ACTION T item; // Inside a read/write lock using (ReadWriteSynchronizationLocker lockContext = ReadWriteLock()) { // Check to see if we are in range if (index >= InternalListContainer.Count) { return; } // Upgrade the lock to a write lock lockContext.Upgrade(); item = InternalListContainer[index]; // Using an undo/redo transaction using OperationTransaction tc = CheckItemAutoRelease(item); // Actually do the removal InternalListContainer.RemoveAt(index); // Push an undo level PushUndoLevel( new RemoveStateChange <T>( index, item)); // Mark the transaction as successful tc.Success(); } // NOTIFICATION // Collection changed RaiseCollectionChangedRemove( item, index); // Property changed RaisePropertyChanged(nameof(Count)); // Contents may have changed ContentsMayHaveChanged(); }
/// <summary> /// Attempts to remove all info related to a key from the dictionary. /// </summary> /// <param name="key">The key to remove data from.</param> /// <returns><see langword="true" /> if the removal was successful, <see langword="false" /> otherwise.</returns> public bool Remove(TKey key) { // PRECONDITIONS // Current object not disposed this.RequiresNotDisposed(); // ACTION bool result; IDictionaryCollectionAdapter <TKey, TValue> container = InternalContainer; // Within a read/write lock using (ReadWriteSynchronizationLocker locker = ReadWriteLock()) { // Find out if there's anything to remove if (!container.TryGetValue( key, out TValue? value)) { return(false); } // Upgrade the locker to a write lock locker.Upgrade(); // Do the actual removal result = container.Remove(key); // Push undo level if (result) { PushUndoLevel( new DictionaryRemoveStateChange <TKey, TValue>( key, value)); } } // NOTIFICATION AND RETURN if (result) { BroadcastChange(); } return(result); }
/// <summary> /// Returns an enumerator that iterates through the collection, from the point in which it currently stands, to the /// end. /// </summary> /// <returns>An enumerator that can be used to iterate through the collection.</returns> public IEnumerator <T> GetEnumerator() { while (true) { T item; using (ReadWriteSynchronizationLocker lck = ReadWriteLock()) { if (storeIndex >= items.Length) { break; } lck.Upgrade(); item = items[storeIndex]; storeIndex++; } yield return(item); } }
/// <summary> /// Removes a key from the dictionary, then acts on its resulting value. /// </summary> /// <param name="key">The key.</param> /// <param name="action">The action.</param> /// <returns><see langword="true" /> if the variable was successfully removed, <see langword="false" /> otherwise.</returns> public bool RemoveThenAct( TKey key, Action <TValue> action) { // PRECONDITIONS // Current object not disposed this.RequiresNotDisposed(); // ACTION int oldIndex; TValue value; // Under read/write lock using (ReadWriteSynchronizationLocker rwl = this.ReadWriteLock()) { if (this.InternalContainer.TryGetValue( key, out value)) { rwl.Upgrade(); if (this.InternalContainer.TryGetValue( key, out value)) { // Re-check within a write lock, to ensure that something else hasn't already removed it. oldIndex = this.InternalContainer.Remove( new KeyValuePair <TKey, TValue>( key, value)); action(value); } else { return(false); } } else { return(false); } } // NOTIFICATIONS // Collection changed if (oldIndex == -1) { // If no index could be found for an item (Dictionary remove) this.RaiseCollectionReset(); } else { // If index was added at a specific index this.RaiseCollectionChangedRemove( new KeyValuePair <TKey, TValue>( key, value), oldIndex); } // Property changed this.RaisePropertyChanged(nameof(this.Count)); // Contents may have changed this.ContentsMayHaveChanged(); return(true); }
/// <summary> /// Creates an item or changes its state, if one exists. /// </summary> /// <param name="key">The key.</param> /// <param name="valueGenerator">The value generator.</param> /// <param name="valueAction">The value action.</param> /// <returns>The created or state-changed item.</returns> public TValue CreateOrChangeState( TKey key, Func <TValue> valueGenerator, Action <TValue> valueAction) { // PRECONDITIONS // Current object not disposed this.RequiresNotDisposed(); // ACTION int newIndex; TValue value; // Under read/write lock using (ReadWriteSynchronizationLocker rwl = this.ReadWriteLock()) { if (this.InternalContainer.TryGetValue( key, out value)) { // Within read lock, if the key is found, return the value. valueAction(value); return(value); } rwl.Upgrade(); if (this.InternalContainer.TryGetValue( key, out value)) { // Re-check within a write lock, to ensure that something else hasn't already added it. valueAction(value); return(value); } // Generate the value value = valueGenerator(); // Add the item newIndex = this.InternalContainer.Add( key, value); } // NOTIFICATIONS // Collection changed if (newIndex == -1) { // If no index could be found for an item (Dictionary add) this.RaiseCollectionReset(); } else { // If index was added at a specific index this.RaiseCollectionChangedAdd( new KeyValuePair <TKey, TValue>( key, value), newIndex); } // Property changed this.RaisePropertyChanged(nameof(this.Count)); // Contents may have changed this.ContentsMayHaveChanged(); return(value); }
/// <summary> /// Gets the item at the specified index. /// </summary> /// <value> /// The item. /// </value> /// <param name="index">The index.</param> /// <returns>The item at the specified index.</returns> public virtual T this[int index] { get { // PRECONDITIONS // Current object not disposed ThrowIfCurrentObjectDisposed(); // ACTION using (ReadLock()) { return(InternalListContainer[index]); } } set { // PRECONDITIONS // Current object not disposed ThrowIfCurrentObjectDisposed(); // ACTION T oldValue; // Inside a read/write lock using (ReadWriteSynchronizationLocker lockContext = ReadWriteLock()) { // Verify if we are within bounds in a read lock if (index >= InternalListContainer.Count) { throw new IndexOutOfRangeException(); } // Upgrade to a write lock lockContext.Upgrade(); // Get the old value oldValue = InternalListContainer[index]; // Two undo/redo transactions using (OperationTransaction tc1 = CheckItemAutoCapture(value)) { using (OperationTransaction tc2 = CheckItemAutoRelease(oldValue)) { // Replace with new value InternalListContainer[index] = value; // Push the undo level PushUndoLevel( new ChangeAtStateChange <T>( index, value, oldValue)); // Mark the second transaction as successful tc2.Success(); } // Mark the first transaction as successful tc1.Success(); } } // NOTIFICATION // Collection changed RaiseCollectionChangedChanged( oldValue, value, index); // Property changed RaisePropertyChanged(nameof(Count)); // Contents may have changed ContentsMayHaveChanged(); } }