【.NET Core】使用autofac實現AOP攔截 記錄所有執行方法

說明

首先,說明一下 

攔截的方法可能是同步,也可能是異步

方法可能無返回值,也有可能是有返回值的

所以,要分情況

 

上代碼

public class LogAOP : IInterceptor
    {
        public LogAOP(ILogger<LogAOP> logger)
        {
            _logger = logger;
        }
        private readonly ILogger<LogAOP> _logger;
        public async void Intercept(IInvocation invocation)
        {
            var dataIntercept = "" +
               $"【當前執行方法】:{ invocation.Method.Name} \r\n" +
               $"【攜帶的參數有】: {JsonConvert.SerializeObject(invocation.Arguments)}\r\n";

            try
            {
                //執行當前方法   
                invocation.Proceed();

                var returnType = invocation.Method.ReturnType;
                //異步方法
                if (IsAsyncMethod(invocation.Method))
                {

                    if (returnType != null && returnType == typeof(Task))
                    {
                        //等待方法返回的Task
                        Func<Task> res = async () => await (Task)invocation.ReturnValue;

                        invocation.ReturnValue = res();
                    }
                    else //Task<TResult>
                    {
                        var returnType2 = invocation.Method.ReflectedType;//獲取返回類型

                        if (returnType2 != null)
                        {
                            var resultType = invocation.Method.ReturnType.GetGenericArguments()[0];

                            MethodInfo methodInfo = typeof(LogAOP).GetMethod("HandleAsync", BindingFlags.Instance | BindingFlags.Public);

                            var mi = methodInfo.MakeGenericMethod(resultType);
                            invocation.ReturnValue = mi.Invoke(this, new[] { invocation.ReturnValue });
                        }
                    }

                    var type = invocation.Method.ReturnType;
                    var resultProperty = type.GetProperty("Result");

                    if (resultProperty != null)
                        dataIntercept += ($"【執行完成結果】:{JsonConvert.SerializeObject(resultProperty.GetValue(invocation.ReturnValue))}");
                }
                //同步方法
                else
                {
                    if (returnType != null && returnType == typeof(void))
                    { 

                    }
                    else
                        dataIntercept += ($"【執行完成結果】:{JsonConvert.SerializeObject(invocation.ReturnValue)}");
                }

                _logger.LogWarning(dataIntercept);

                await Task.Run(() =>
                {
                    Parallel.For(0, 1, e =>
                    {
                        LogHelper.Log("AOPLog", dataIntercept);
                    });
                });
            }
            catch (Exception ex)
            {
                LogEx(ex, dataIntercept);
            }
        }

        //構造等待返回值的異步方法
        public async Task<T> HandleAsync<T>(Task<T> task)
        {
            var t = await task;

            return t;
        }

        private void LogEx(Exception ex, string dataIntercept)
        {
            if (ex != null)
            {
                //執行的 service 中,捕獲異常
                dataIntercept += ($"【執行完成結果】:方法中出現異常:{ex.Message + ex.InnerException}\r\n");

                // 異常日誌裏有詳細的堆棧信息
                Parallel.For(0, 1, e =>
                {
                    LogHelper.Log("AOPLog", dataIntercept);
                    _logger.LogWarning(dataIntercept);
                });
            }
        }

        /// <summary>
        /// 判斷是否異步方法
        /// </summary>
        public static bool IsAsyncMethod(MethodInfo method)
        {
            return (
                method.ReturnType == typeof(Task) ||
                (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
                );
        }
    }

在Startup中,添加攔截器

//Autofac服務工廠
public void ConfigureContainer(ContainerBuilder builder)
{
    var basePath = AppContext.BaseDirectory;

    var bllFilePath = Path.Combine(basePath, "Wang.Blog.BLL.dll");

    List<Type> aops = new List<Type>();

    builder.RegisterType<LogAOP>();
    aops.Add(typeof(LogAOP));
    
    //BLL層註冊服務
    builder.RegisterAssemblyTypes(Assembly.LoadFile(bllFilePath))
        .AsImplementedInterfaces()
        .InstancePerDependency()
        .EnableInterfaceInterceptors()
        .InterceptedBy(aops.ToArray())//註冊攔截器
        ;
}

日誌效果

參考:

https://blog.csdn.net/q932104843/article/details/97611912

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章