【.NET Core】使用autofac实现AOP拦截 记录所有执行方法

本文介绍了一种使用AOP实现的日志拦截器设计,该设计能够处理同步和异步方法,支持无返回值和有返回值的情况,通过代码示例详细展示了如何在.NET环境中配置和使用该拦截器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说明

首先,说明一下 

拦截的方法可能是同步,也可能是异步

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

所以,要分情况

 

上代码

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

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GreAmbWang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值