예제 #1
0
        public ExecuteOperationCellIfNecessaryOp <TValue> DeepCloneWithCell(IOperationOutputCell <TValue> cell)
        {
            var result = new ExecuteOperationCellIfNecessaryOp <TValue>(
                cell);

            return(result);
        }
예제 #2
0
        /// <summary>
        /// Gets the outcome of executing an <see cref="IOperationOutputCell{TValue}"/>'s <see cref="IOperationOutputCell{TValue}.Operation"/>.
        /// </summary>
        /// <param name="cell">The cell.</param>
        /// <returns>
        /// The outcome of executing an <see cref="IOperationOutputCell{TValue}"/>'s <see cref="IOperationOutputCell{TValue}.Operation"/>.
        /// </returns>
        public static CellOpExecutionOutcome GetCellOpExecutionOutcome(
            this IOperationOutputCell cell)
        {
            if (cell == null)
            {
                throw new ArgumentNullException(nameof(cell));
            }

            var executionStatus = cell.GetCellOpExecutionStatus();

            switch (executionStatus)
            {
            case CellOpExecutionStatus.DeemedNotApplicable:
                return(CellOpExecutionOutcome.NotApplicable);

            case CellOpExecutionStatus.Aborted:
                return(CellOpExecutionOutcome.Aborted);

            case CellOpExecutionStatus.Failed:
                return(CellOpExecutionOutcome.Failed);

            case CellOpExecutionStatus.Completed:
                return(CellOpExecutionOutcome.Completed);

            default:
                return(CellOpExecutionOutcome.Unknown);
            }
        }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ExecuteOperationCellIfNecessaryOp{TValue}"/> class.
        /// </summary>
        /// <param name="cell">The cell.</param>
        public ExecuteOperationCellIfNecessaryOp(
            IOperationOutputCell <TValue> cell)
        {
            if (cell == null)
            {
                throw new ArgumentNullException(nameof(cell));
            }

            this.Cell = cell;
        }
예제 #4
0
        /// <summary>
        /// Gets the status of the execution of an <see cref="IOperationOutputCell{TValue}"/>'s <see cref="IOperationOutputCell{TValue}.Operation"/>.
        /// </summary>
        /// <param name="cell">The cell.</param>
        /// <returns>
        /// The status of the execution of an <see cref="IOperationOutputCell{TValue}"/>'s <see cref="IOperationOutputCell{TValue}.Operation"/>.
        /// </returns>
        public static CellOpExecutionStatus GetCellOpExecutionStatus(
            this IOperationOutputCell cell)
        {
            if (cell == null)
            {
                throw new ArgumentNullException(nameof(cell));
            }

            CellOpExecutionStatus result;

            var lastCellOpExecutionEvent = cell.OperationExecutionEvents?.LastOrDefault();

            if (lastCellOpExecutionEvent == null)
            {
                result = CellOpExecutionStatus.NotExecuted;
            }
            else if (lastCellOpExecutionEvent is CellOpExecutionClearedEvent)
            {
                result = CellOpExecutionStatus.NotExecuted;
            }
            else if (lastCellOpExecutionEvent is CellOpExecutionAbortedEvent)
            {
                result = CellOpExecutionStatus.Aborted;
            }
            else if (lastCellOpExecutionEvent is CellOpExecutionDeemedNotApplicableEvent)
            {
                result = CellOpExecutionStatus.DeemedNotApplicable;
            }
            else if (lastCellOpExecutionEvent is CellOpExecutionFailedEvent)
            {
                result = CellOpExecutionStatus.Failed;
            }
            else if (lastCellOpExecutionEvent.GetType().GetGenericTypeDefinitionOrSpecifiedType() == typeof(CellOpExecutionCompletedEvent <>))
            {
                result = CellOpExecutionStatus.Completed;
            }
            else
            {
                throw new InvalidOperationException(Invariant($"Cannot determine the {nameof(CellOpExecutionStatus)} of the specified cell."));
            }

            return(result);
        }
예제 #5
0
        private static IOperation BuildExecuteOperationCellIfNecessaryOp(
            this IOperationOutputCell operationCell)
        {
            var valueType = operationCell.GetValueTypeOrNull();

            if (valueType == null)
            {
                throw new InvalidOperationException(Invariant($"This kind of cell is supposed to have a value type: {operationCell.GetType().ToStringReadable()}."));
            }

            if (!CachedTypeToExecuteOperationCellIfNecessaryOpConstructorInfoMap.TryGetValue(valueType, out var executeOperationCellIfNecessaryOpConstructorInfo))
            {
                executeOperationCellIfNecessaryOpConstructorInfo = typeof(ExecuteOperationCellIfNecessaryOp <>).MakeGenericType(valueType).GetConstructors().Single();

                CachedTypeToExecuteOperationCellIfNecessaryOpConstructorInfoMap.TryAdd(valueType, executeOperationCellIfNecessaryOpConstructorInfo);
            }

            // ReSharper disable once CoVariantArrayConversion
            var result = (IOperation)executeOperationCellIfNecessaryOpConstructorInfo.Invoke(new[] { operationCell });

            return(result);
        }
예제 #6
0
        private async Task ExecuteOperationCellIfNecessaryAsync(
            IOperationOutputCell <TValue> cell)
        {
            // NOTE: THIS CODE IS A NEAR DUPLICATE OF THE SYNC METHOD ABOVE; NO GOOD WAY TO D.R.Y. IT OUT
            if (cell.GetCellOpExecutionStatus() == CellOpExecutionStatus.NotExecuted)
            {
                CellOpExecutionEventBase operationExecutionEvent;

                try
                {
                    var operationResult = await this.protocolFactory.GetProtocolAndExecuteViaReflectionAsync <TValue>(cell.Operation);

                    operationExecutionEvent = new CellOpExecutionCompletedEvent <TValue>(this.timestampUtc, null, operationResult);
                }
                catch (OpExecutionAbortedExceptionBase ex)
                {
                    operationExecutionEvent = new CellOpExecutionAbortedEvent(this.timestampUtc, ex.ToString());
                }
                catch (OpExecutionDeemedNotApplicableExceptionBase ex)
                {
                    operationExecutionEvent = new CellOpExecutionDeemedNotApplicableEvent(this.timestampUtc, ex.ToString());
                }
                catch (Exception ex)
                {
                    // The "proper" exception for a protocol to throw is an OpExecutionFailedExceptionBase.
                    // Protocol authors might not comply.
                    operationExecutionEvent = new CellOpExecutionFailedEvent(this.timestampUtc, ex.ToString());
                }

                cell.Record(operationExecutionEvent);
            }
            else if (cell.OperationExecutionEvents.Last().TimestampUtc != this.timestampUtc)
            {
                throw new InvalidOperationException("Something went wrong.  The operation was executed, but the recorded timestamp doesn't match this timestamp.");
            }
        }