Ejemplo n.º 1
0
        /// <inheritdoc/>
        public virtual void EndTransaction(string name, AggregateActionItemDelegate aggregateActionItems, bool reverseOrderOnUndo = true)
        {
            if (TransactionStack.Count == 0)
            {
                throw new InvalidOperationException(Properties.ExceptionMessages.CannotEndNoTransactionInProgress);
            }

            var currentTransaction = TransactionStack.Pop();

            if (currentTransaction.Count > 0)
            {
                var result = aggregateActionItems(currentTransaction);
                var aggregateActionItem = result as IAggregateActionItem;
                if (aggregateActionItem != null)
                {
                    aggregateActionItem.ReverseOrderOnUndo = reverseOrderOnUndo;
                }
                Add(result);
                TransactionEnded?.Invoke(this, new ActionItemsEventArgs <IActionItem>(result));
            }
            else
            {
                TransactionDiscarded?.Invoke(this, new ActionItemsEventArgs <IActionItem>(new IActionItem[0]));
            }
        }
Ejemplo n.º 2
0
        /// <inheritdoc/>
        public virtual void DiscardTransaction()
        {
            if (TransactionStack.Count == 0)
            {
                throw new InvalidOperationException(Properties.ExceptionMessages.CannotEndNoTransactionInProgress);
            }
            var actions = TransactionStack.Pop();

            TransactionDiscarded?.Invoke(this, new ActionItemsEventArgs <IActionItem>(actions.ToArray()));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Purges the stack from the given index (included) to the top of the stack.
        /// </summary>
        /// <param name="index">The index from which to purge the stack.</param>
        private void PurgeFromIndex(int index)
        {
            if (index < 0 || index > transactions.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(index));
            }

            if (transactions.Count - index > 0)
            {
                var discardedTransactions = new IReadOnlyTransaction[transactions.Count - index];
                for (var i = index; i < transactions.Count; ++i)
                {
                    transactions[i].Interface.Freeze();
                    discardedTransactions[i - index] = transactions[i];
                }
                transactions.RemoveRange(index, transactions.Count - index);
                TransactionDiscarded?.Invoke(this, new TransactionsDiscardedEventArgs(discardedTransactions, DiscardReason.StackPurged));
            }
        }
Ejemplo n.º 4
0
        /// <inheritdoc/>
        public virtual void EndTransaction(string name, Func <IReadOnlyCollection <IActionItem>, IActionItem> aggregateActionItems)
        {
            if (TransactionStack.Count == 0)
            {
                throw new InvalidOperationException(Properties.ExceptionMessages.CannotEndNoTransactionInProgress);
            }

            var currentTransaction = TransactionStack.Pop();

            if (currentTransaction.Count > 0)
            {
                var aggregateActionItem = aggregateActionItems(currentTransaction);
                Add(aggregateActionItem);
                TransactionEnded?.Invoke(this, new ActionItemsEventArgs <IActionItem>(aggregateActionItem));
            }
            else
            {
                TransactionDiscarded?.Invoke(this, new ActionItemsEventArgs <IActionItem>(new IActionItem[0]));
            }
        }
Ejemplo n.º 5
0
        /// <inheritdoc/>
        public void CompleteTransaction(Transaction transaction)
        {
            lock (lockObject)
            {
                try
                {
                    if (transactionsInProgress.Count == 0)
                    {
                        throw new TransactionException("There is not transaction in progress in the transaction stack.");
                    }

                    if (transaction != transactionsInProgress.Pop())
                    {
                        throw new TransactionException("The transaction being completed is not that last created transaction.");
                    }

                    // Check if we're completing the last transaction
                    TransactionInProgress = transactionsInProgress.Count > 0;

                    // Ignore the transaction if it is empty
                    if (transaction.IsEmpty)
                    {
                        return;
                    }

                    // If this transaction has no effect, discard it.
                    if (transaction.Operations.All(x => !x.HasEffect))
                    {
                        return;
                    }

                    // If we're not the last transaction, consider this transaction as an operation of its parent transaction
                    if (TransactionInProgress)
                    {
                        // Avoid useless nested transaction if we have a single operation inside.
                        PushOperation(transaction.Operations.Count == 1 ? transaction.Operations.Single() : transaction);
                        return;
                    }

                    // Remove transactions that will be overwritten by this one
                    if (currentPosition < transactions.Count)
                    {
                        PurgeFromIndex(currentPosition);
                    }

                    if (currentPosition == Capacity)
                    {
                        // If the stack has a capacity of 0, immediately freeze the new transaction.
                        var oldestTransaction = Capacity > 0 ? transactions[0] : transaction;
                        oldestTransaction.Interface.Freeze();

                        for (var i = 1; i < transactions.Count; ++i)
                        {
                            transactions[i - 1] = transactions[i];
                        }
                        if (Capacity > 0)
                        {
                            transactions[--currentPosition] = null;
                        }
                        TransactionDiscarded?.Invoke(this, new TransactionsDiscardedEventArgs(oldestTransaction, DiscardReason.StackFull));
                    }
                    if (Capacity > 0)
                    {
                        if (currentPosition == transactions.Count)
                        {
                            transactions.Add(transaction);
                        }
                        else
                        {
                            transactions[currentPosition] = transaction;
                        }
                        ++currentPosition;
                    }
                }
                finally
                {
                    if (!TransactionInProgress)
                    {
                        TransactionCompleted?.Invoke(this, new TransactionEventArgs(transaction));
                    }
                }
            }
        }