private async Task <LocatedCellHavingValue> GetCellAndExecuteOperationIfNecessaryAsync( IReturningOperation <CellLocatorBase> cellLocatorOp) { // NOTE: THIS CODE IS A NEAR DUPLICATE OF THE SYNC METHOD ABOVE; NO GOOD WAY TO D.R.Y. IT OUT var cellLocator = await this.protocolFactory.GetProtocolAndExecuteViaReflectionAsync <CellLocatorBase>(cellLocatorOp); var cell = this.GetCell(cellLocator); if (!(cell is IGetCellValue cellWithValue)) { throw new CellNotFoundException(Invariant($"The operation addresses a cell whose type is not an {typeof(IGetCellValue).ToStringReadable()}: {cell.GetType().ToStringReadable()}."), cellLocator); } // This is necessary because we can't simply use new ExecuteOperationCellIfNecessaryOp<TValue>() // TValue is the TValue of THIS protocol factory. // HasCellValueOp does not have TValue in it's generic arguments; ALL instances of // DataStructureCellProtocols can execute that operation and the chain-of-responsibility // protocol factory will simply use the first instance of DataStructureCellProtocols that is registered. // So TValue of this factory might be int whereas the cell's TValue is a decimal. var executeOperationCellIfNecessaryOp = DataStructureCellProtocols.GetExecuteOperationCellIfNecessaryOpOrNull(cell); if (executeOperationCellIfNecessaryOp != null) { await this.protocolFactory.GetProtocolAndExecuteViaReflectionAsync(executeOperationCellIfNecessaryOp); } var result = new LocatedCellHavingValue { Cell = cellWithValue, CellLocator = cellLocator, }; return(result); }
/// <inheritdoc /> public async Task ExecuteAsync( CheckAvailabilityOfCellIfNecessaryOp operation) { // NOTE: THIS CODE IS A NEAR DUPLICATE OF THE SYNC METHOD ABOVE; NO GOOD WAY TO D.R.Y. IT OUT if (operation == null) { throw new ArgumentNullException(nameof(operation)); } var cell = operation.Cell; try { DataStructureCellProtocols.CurrentCellStack.Push(cell); await this.CheckAvailabilityOfCellIfNecessaryAsync(cell); } finally { var poppedCell = DataStructureCellProtocols.CurrentCellStack.Pop(); DataStructureCellProtocols.ThrowIfUnexpectedCellPoppedOffCurrentCellStack(cell, poppedCell); } }
/// <inheritdoc /> public void Execute( ValidateCellIfNecessaryOp operation) { // NOTE: THIS CODE IS A NEAR DUPLICATE OF THE ASYNC METHOD BELOW; NO GOOD WAY TO D.R.Y. IT OUT if (operation == null) { throw new ArgumentNullException(nameof(operation)); } var cell = operation.Cell; try { DataStructureCellProtocols.CurrentCellStack.Push(cell); this.ValidateCellIfNecessary(cell); } finally { var poppedCell = DataStructureCellProtocols.CurrentCellStack.Pop(); DataStructureCellProtocols.ThrowIfUnexpectedCellPoppedOffCurrentCellStack(cell, poppedCell); } }