/// <summary> /// Process the output from the call so far and optionally modify the output. /// </summary> /// <param name="input">The input.</param> /// <param name="methodReturn">The method return.</param> /// <param name="callData">The per-call data.</param> /// <returns>IMethodReturn.</returns> protected override IMethodReturn PostInvoke( IMethodInvocation input, IMethodReturn methodReturn, CallTraceData callData) { // async methods are always dumped in ContinueWith if (!callData.Trace || !LogWriter.IsLoggingEnabled() || methodReturn.IsAsyncCall()) { return(methodReturn); } callData.ReturnValue = methodReturn.ReturnValue; callData.OutputValues = methodReturn.Outputs; callData.Exception = methodReturn.Exception; // if necessary wait for the async LogBeforeCall to finish if (callData.LogBeforeCall != null && !input.IsAsyncCall()) { callData.LogBeforeCall.GetAwaiter().GetResult(); } LogPostInvoke(input, callData).GetAwaiter().GetResult(); return(methodReturn); }
protected override IMethodReturn PostInvoke( IMethodInvocation input, IMethodReturn methodReturn, TransactionScope transactionScope) { if (input == null) { throw new ArgumentNullException(nameof(input)); } if (methodReturn == null) { throw new ArgumentNullException(nameof(methodReturn)); } if (methodReturn.IsAsyncCall()) { return(methodReturn); // return the task, do not clean-up yet } try { if (methodReturn.Exception != null) { if (methodReturn.Exception is AggregateException ax) { if (ax.InnerExceptions.Count == 1 && ax.InnerExceptions[0].IsTransient()) { return(input.CreateExceptionMethodReturn(new RepeatableOperationException(ax.InnerExceptions[0]))); } } else if (methodReturn.Exception.IsTransient()) { return(input.CreateExceptionMethodReturn(new RepeatableOperationException(methodReturn.Exception))); } return(methodReturn); // return the exception (and cleanup) } var hasRepository = (IHasRepository)input.Target; // get the repository var repository = hasRepository.Repository; if (repository == null) { throw new InvalidOperationException(nameof(IHasRepository) + " must return a non-null repository."); } // commit repository.CommitChanges(); transactionScope?.Complete(); return(methodReturn); } catch (AggregateException x) { VmAspectsEventSource.Log.CallHandlerFails(input, x); if (x.InnerExceptions.Count == 1 && x.InnerExceptions[0].IsTransient()) { return(input.CreateExceptionMethodReturn(new RepeatableOperationException(x.InnerExceptions[0]))); } throw; } catch (Exception x) { VmAspectsEventSource.Log.CallHandlerFails(input, x); if (x.IsTransient()) { return(input.CreateExceptionMethodReturn(new RepeatableOperationException(x))); } return(input.CreateExceptionMethodReturn(x)); } finally { // and clean-up transactionScope?.Dispose(); } }