protected override object Invoke(MethodInfo targetMethod, object[] args) { Stopwatch stopwatch = Stopwatch.StartNew(); bool syncResult = true; try { parameters.BeforeAction(parameters.Logger, targetMethod, args); parameters.Logger.LogTrace("Method '{targetMethodName}' parameters '{parameters}'", targetMethod.Name, args); var result = targetMethod.Invoke(parameters.DecoratedService, args); if (result is Task task) { syncResult = false; task.ContinueWith((completedTask) => { try { if (completedTask.IsCompletedSuccessfully) { Type type = task.GetType(); if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Task <>)) { if (parameters.Logger.IsEnabled(LogLevel.Trace)) { var result = type.GetProperty("Result").GetValue(task); parameters.Logger.LogTrace("Task completed successfully from '{targetMethodName}' with '{result}'", targetMethod.Name, result); } } } else { parameters.Logger.LogTrace("Task completed with '{status}'", task.Status); if (completedTask.Exception != null) { parameters.ErrorAction(parameters.Logger, completedTask.Exception, targetMethod, args); } } return(result); } finally { parameters.Logger.LogTrace("Completed '{targetMethodName}' in '{timeElapsedInTicks}'", targetMethod.Name, stopwatch.Elapsed.Ticks); parameters.AfterAction(parameters.Logger, targetMethod, args); } }, scheduler: TaskScheduler.FromCurrentSynchronizationContext()); } if (syncResult) { if (targetMethod.ReturnType == typeof(void)) { parameters.Logger.LogTrace("Completed '{targetMethodName}' in '{timeElapsedInTicks}'", targetMethod.Name, stopwatch.Elapsed.Ticks); } else { parameters.Logger.LogTrace("Completed '{targetMethodName}' with '{result}' in '{timeElapsedInTicks}'", targetMethod.Name, result, stopwatch.Elapsed.Ticks); } } return(result); } catch (Exception ex) { parameters.ErrorAction(parameters.Logger, ex, targetMethod, args); throw; } finally { if (syncResult) { parameters.AfterAction(parameters.Logger, targetMethod, args); } } }