| using Castle.DynamicProxy; | 
| using Microsoft.AspNetCore.Http; | 
| using Microsoft.AspNetCore.SignalR; | 
| using Newtonsoft.Json; | 
| using StackExchange.Profiling; | 
| using System; | 
| using System.Collections.Generic; | 
| using System.ComponentModel; | 
| using System.Linq; | 
| using System.Reflection; | 
| using System.Text; | 
| using System.Threading.Tasks; | 
| using WIDESEA_Core.Helper; | 
| using WIDESEA_Core.LogHelper; | 
|   | 
| namespace WIDESEA_Core.AOP | 
| { | 
|     /// <summary> | 
|     /// 拦截器BlogLogAOP 继承IInterceptor接口 | 
|     /// </summary> | 
|     public class LogAOP : IInterceptor | 
|     { | 
|         private readonly IHttpContextAccessor _accessor; | 
|   | 
|         public LogAOP(IHttpContextAccessor accessor) | 
|         { | 
|             _accessor = accessor; | 
|         } | 
|   | 
|         /// <summary> | 
|         /// 实例化IInterceptor唯一方法 | 
|         /// </summary> | 
|         /// <param name="invocation">包含被拦截方法的信息</param> | 
|         public void Intercept(IInvocation invocation) | 
|         { | 
|             string UserName = _accessor.HttpContext?.User?.Identity?.Name; | 
|             string json; | 
|             try | 
|             { | 
|                 if (invocation.Arguments.Any()) | 
|                 { | 
|                     json = JsonConvert.SerializeObject(invocation.Arguments); | 
|                 } | 
|                 else | 
|                 { | 
|                     json = "无参数"; | 
|                 } | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 json = "无法序列化,可能是兰姆达表达式等原因造成,按照框架优化代码" + ex.ToString(); | 
|             } | 
|   | 
|             DateTime startTime = DateTime.Now; | 
|             AOPLogInfo apiLogAopInfo = new AOPLogInfo | 
|             { | 
|                 RequestTime = startTime.ToString("yyyy-MM-dd hh:mm:ss fff"), | 
|                 OpUserName = "【当前操作用户】:" + UserName, | 
|                 RequestMethodName = "【当前执行方法】:" + invocation.Method.Name, | 
|                 RequestParamsName = "【携带的参数有】:" + string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()), | 
|                 RequestParamsData = json | 
|             }; | 
|   | 
|             var dataIntercept = $""; | 
|   | 
|             try | 
|             { | 
|                 MiniProfiler.Current.Step($"执行{invocation.InvocationTarget}.{invocation.Method.Name}()方法 -> "); | 
|                 //在被拦截的方法执行完毕后 继续执行当前方法,注意是被拦截的是异步的 | 
|                 invocation.Proceed(); | 
|   | 
|                 // 异步获取异常,先执行 | 
|                 if (IsAsyncMethod(invocation.Method)) | 
|                 { | 
|                     #region 方案一 | 
|   | 
|                     //Wait task execution and modify return value | 
|                     if (invocation.Method.ReturnType == typeof(Task)) | 
|                     { | 
|                         invocation.ReturnValue = InternalAsyncHelper.AwaitTaskWithPostActionAndFinally( | 
|                             (Task)invocation.ReturnValue, | 
|                             async () => await SuccessAction(invocation, apiLogAopInfo, startTime), /*成功时执行*/ | 
|                             ex => | 
|                             { | 
|                                 LogEx(ex, apiLogAopInfo); | 
|                             }); | 
|                     } | 
|                     //Task<TResult> | 
|                     else | 
|                     { | 
|                         invocation.ReturnValue = InternalAsyncHelper.CallAwaitTaskWithPostActionAndFinallyAndGetResult( | 
|                             invocation.Method.ReturnType.GenericTypeArguments[0], | 
|                             invocation.ReturnValue, | 
|                             //async () => await SuccessAction(invocation, dataIntercept),/*成功时执行*/ | 
|                             async (o) => await SuccessAction(invocation, apiLogAopInfo, startTime, o), /*成功时执行*/ | 
|                             ex => | 
|                             { | 
|                                 LogEx(ex, apiLogAopInfo); | 
|                             }); | 
|                     } | 
|   | 
|                     #endregion 方案一 | 
|   | 
|                     // 如果方案一不行,试试这个方案 | 
|                     //#region 方案二 | 
|   | 
|                     //var type = invocation.Method.ReturnType; | 
|                     //var resultProperty = type.GetProperty("Result"); | 
|                     //DateTime endTime = DateTime.Now; | 
|                     //string ResponseTime = (endTime - startTime).Milliseconds.ToString(); | 
|                     //apiLogAopInfo.ResponseTime = endTime.ToString("yyyy-MM-dd hh:mm:ss fff"); | 
|                     //apiLogAopInfo.ResponseIntervalTime = ResponseTime + "ms"; | 
|                     //apiLogAopInfo.ResponseJsonData = JsonConvert.SerializeObject(resultProperty.GetValue(invocation.ReturnValue)); | 
|   | 
|                     ////dataIntercept += ($"【响应时间】:{ResponseTime}ms\r\n"); | 
|                     ////dataIntercept += ($"【执行完成时间】:{endTime.ToString("yyyy-MM-dd hh:mm:ss fff")}\r\n"); | 
|                     ////dataIntercept += ($"【执行完成结果】:{JsonConvert.SerializeObject(resultProperty.GetValue(invocation.ReturnValue))}\r\n"); | 
|   | 
|                     //Parallel.For(0, 1, e => | 
|                     //{ | 
|                     //    //LogLock.OutLogAOP("AOPLog", new string[] { dataIntercept }); | 
|                     //    LogLock.OutLogAOP("AOPLog", new string[] { apiLogAopInfo.GetType().ToString() + " - ResponseJsonDataType:" + type, JsonConvert.SerializeObject(apiLogAopInfo) }); | 
|                     //}); | 
|   | 
|                     //#endregion | 
|                 } | 
|                 else | 
|                 { | 
|                     // 同步1 | 
|                     string jsonResult; | 
|                     try | 
|                     { | 
|                         jsonResult = JsonConvert.SerializeObject(invocation.ReturnValue); | 
|                     } | 
|                     catch (Exception ex) | 
|                     { | 
|                         jsonResult = "无法序列化,可能是兰姆达表达式等原因造成,按照框架优化代码" + ex.ToString(); | 
|                     } | 
|   | 
|                     var type = invocation.Method.ReturnType; | 
|                     var resultProperty = type.GetProperty("Result"); | 
|                     DateTime endTime = DateTime.Now; | 
|                     string ResponseTime = (endTime - startTime).Milliseconds.ToString(); | 
|                     apiLogAopInfo.ResponseTime = endTime.ToString("yyyy-MM-dd hh:mm:ss fff"); | 
|                     apiLogAopInfo.ResponseIntervalTime = ResponseTime + "ms"; | 
|                     apiLogAopInfo.ResponseJsonData = jsonResult; | 
|                     Parallel.For(0, 1, e => | 
|                     { | 
|                         LogLock.OutLogAOP("AOPLog", new string[] { apiLogAopInfo.GetType().ToString(), JsonConvert.SerializeObject(apiLogAopInfo) }); | 
|                     }); | 
|                 } | 
|             } | 
|             catch (Exception ex) // 同步2 | 
|             { | 
|                 LogEx(ex, apiLogAopInfo); | 
|                 throw; | 
|             } | 
|         } | 
|   | 
|         private async Task SuccessAction(IInvocation invocation, AOPLogInfo apiLogAopInfo, DateTime startTime, object o = null) | 
|         { | 
|             DateTime endTime = DateTime.Now; | 
|             string ResponseTime = (endTime - startTime).Milliseconds.ToString(); | 
|             apiLogAopInfo.ResponseTime = endTime.ToString("yyyy-MM-dd hh:mm:ss fff"); | 
|             apiLogAopInfo.ResponseIntervalTime = ResponseTime + "ms"; | 
|             apiLogAopInfo.ResponseJsonData = JsonConvert.SerializeObject(o); | 
|   | 
|             await Task.Run(() => | 
|             { | 
|                 Parallel.For(0, 1, e => | 
|                 { | 
|                     //LogLock.OutSql2Log("AOPLog", new string[] { JsonConvert.SerializeObject(apiLogAopInfo) }); | 
|                     LogLock.OutLogAOP("AOPLog", new string[] { apiLogAopInfo.GetType().ToString(), JsonConvert.SerializeObject(apiLogAopInfo) }); | 
|                 }); | 
|             }); | 
|         } | 
|   | 
|         private void LogEx(Exception ex, AOPLogInfo dataIntercept) | 
|         { | 
|             if (ex != null) | 
|             { | 
|                 //执行的 service 中,收录异常 | 
|                 MiniProfiler.Current.CustomTiming("Errors:", ex.Message); | 
|                 //执行的 service 中,捕获异常 | 
|                 AOPLogExInfo apiLogAopExInfo = new AOPLogExInfo | 
|                 { | 
|                     ExMessage = ex.Message, | 
|                     InnerException = "InnerException-内部异常:\r\n" + (ex.InnerException == null ? "" : ex.InnerException.InnerException.ToString()) + | 
|                                      "\r\nStackTrace-堆栈跟踪:\r\n" + (ex.StackTrace == null ? "" : ex.StackTrace.ToString()), | 
|                     ApiLogAopInfo = dataIntercept | 
|                 }; | 
|                 // 异常日志里有详细的堆栈信息 | 
|                 Parallel.For(0, 1, e => | 
|                 { | 
|                     LogLock.OutLogAOP("AOPLogEx", new string[] { apiLogAopExInfo.GetType().ToString(), JsonConvert.SerializeObject(apiLogAopExInfo) }); | 
|                 }); | 
|             } | 
|         } | 
|   | 
|         public static bool IsAsyncMethod(MethodInfo method) | 
|         { | 
|             return | 
|                 method.ReturnType == typeof(Task) || | 
|                 method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>) | 
|             ; | 
|         } | 
|     } | 
|   | 
|     internal static class InternalAsyncHelper | 
|     { | 
|         public static async Task AwaitTaskWithPostActionAndFinally(Task actualReturnValue, Func<Task> postAction, Action<Exception> finalAction) | 
|         { | 
|             Exception exception = null; | 
|   | 
|             try | 
|             { | 
|                 await actualReturnValue; | 
|                 await postAction(); | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 exception = ex; | 
|             } | 
|             finally | 
|             { | 
|                 finalAction(exception); | 
|             } | 
|         } | 
|   | 
|         public static async Task<T> AwaitTaskWithPostActionAndFinallyAndGetResult<T>(Task<T> actualReturnValue, Func<object, Task> postAction, | 
|             Action<Exception> finalAction) | 
|         { | 
|             Exception exception = null; | 
|             try | 
|             { | 
|                 var result = await actualReturnValue; | 
|                 await postAction(result); | 
|                 return result; | 
|             } | 
|             catch (Exception ex) | 
|             { | 
|                 exception = ex; | 
|                 throw; | 
|             } | 
|             finally | 
|             { | 
|                 finalAction(exception); | 
|             } | 
|         } | 
|   | 
|         public static object CallAwaitTaskWithPostActionAndFinallyAndGetResult(Type taskReturnType, object actualReturnValue, | 
|             Func<object, Task> action, Action<Exception> finalAction) | 
|         { | 
|             return typeof(InternalAsyncHelper) | 
|                 .GetMethod("AwaitTaskWithPostActionAndFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static) | 
|                 .MakeGenericMethod(taskReturnType) | 
|                 .Invoke(null, new object[] { actualReturnValue, action, finalAction }); | 
|         } | 
|     } | 
|   | 
|     public class AOPLogInfo | 
|     { | 
|         /// <summary> | 
|         /// 请求时间 | 
|         /// </summary> | 
|         [Description("请求时间")] | 
|         public string RequestTime { get; set; } = string.Empty; | 
|   | 
|         /// <summary> | 
|         /// 操作人员 | 
|         /// </summary> | 
|         [Description("操作人员")] | 
|         public string OpUserName { get; set; } = string.Empty; | 
|   | 
|         /// <summary> | 
|         /// 请求方法名 | 
|         /// </summary> | 
|         [Description("请求方法名")] | 
|         public string RequestMethodName { get; set; } = string.Empty; | 
|   | 
|         /// <summary> | 
|         /// 请求参数名 | 
|         /// </summary> | 
|         [Description("请求参数名")] | 
|         public string RequestParamsName { get; set; } = string.Empty; | 
|   | 
|         /// <summary> | 
|         /// 请求参数数据JSON | 
|         /// </summary> | 
|         [Description("请求参数数据JSON")] | 
|         public string RequestParamsData { get; set; } = string.Empty; | 
|   | 
|         /// <summary> | 
|         /// 请求响应间隔时间 | 
|         /// </summary> | 
|         [Description("请求响应间隔时间")] | 
|         public string ResponseIntervalTime { get; set; } = string.Empty; | 
|   | 
|         /// <summary> | 
|         /// 响应时间 | 
|         /// </summary> | 
|         [Description("响应时间")] | 
|         public string ResponseTime { get; set; } = string.Empty; | 
|   | 
|         /// <summary> | 
|         /// 响应结果 | 
|         /// </summary> | 
|         [Description("响应结果")] | 
|         public string ResponseJsonData { get; set; } = string.Empty; | 
|     } | 
|   | 
|     public class AOPLogExInfo | 
|     { | 
|         public AOPLogInfo ApiLogAopInfo { get; set; } | 
|   | 
|         /// <summary> | 
|         /// 异常 | 
|         /// </summary> | 
|         [Description("异常")] | 
|         public string InnerException { get; set; } = string.Empty; | 
|   | 
|         /// <summary> | 
|         /// 异常信息 | 
|         /// </summary> | 
|         [Description("异常信息")] | 
|         public string ExMessage { get; set; } = string.Empty; | 
|     } | 
| } |