예제 #1
0
        /// <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);
        }
예제 #2
0
        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();
            }
        }