Netcore 中间件之Autofac(依赖注入)的基本使用 日志功能实现(AOP)2.1

Autofac(依赖注入)的基本使用(Netcore2.X)

起:

在项目编程中,经常要记录整个项目的接口和调用情况。如果只是控制器的话,直接使用过滤器或者是中间件即可。或者也可以写切面来记录。
但是如果想看下与Service或者Repository层的调用情况,好像目前咱们只能在Service层或者Repository层去写日志记录了,那样的话,不仅耦合性就会变的很高,不符合解耦的要求。这个时候就需要用到AOP和Autofac的Castle结合的方法。

注:
1.本文项目基于上一章Autofac(依赖注入)的基本使用(Netcore2.X)
2.本文的重点并不是写日志,而是使用Autofac达成符合AOP的日志功能能。

基础:

所需nugut包:
Autofac.Extensions.DependencyInjection
Autofac.Extras.DynamicProxy

新建Log的AOP拦截器,并实现IInterceptor的Intercept方法

步骤如下:
1.继承IInterceptor
2.实例化IInterceptor唯一方法
3.记录被拦截方法信息的日志信息
4.继续执行当前方法
5.记录日志

    /// <summary>
    /// 拦截器LogAOP ,实现IInterceptor 
    /// 面向切面的日志使用
    /// </summary>
    public class LogAOP : IInterceptor
    {
        /// <summary>
        /// 实例化IInterceptor唯一方法
        /// </summary>
        /// <param name="invocation">包含被拦截的方法信息</param>
        public void Intercept(IInvocation invocation)
        {
            //记录被拦截方法信息的日志信息
            var dataIntercept =    
                $"【当前执行方法】:{invocation.Method.Name}" +    
                $"【携带的参数有】:{string.Join(",", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())} \r\n";

            //在被拦截的方法执行完毕后 继续执行当前方法
            invocation.Proceed();

            //记录日志
            WriteLine(dataIntercept);
        }
    }

Startup完成注入

步骤如下:
1.拦截器类注册
2.在对应注入中使用拦截器类
在这里插入图片描述
在这里插入图片描述
完整代码如下


            #region Autofac注入
            //获取项目路径
            //var basePath = AppContext.BaseDirectory;
            //var basePath = Microsoft.DotNet.PlatformAbstractions.ApplicationEnvironment.ApplicationBasePath;//这种方法可以取得路径

            初始化AutoFac容器
            var builder = new ContainerBuilder();

            //日志拦截器的依赖注入
            builder.RegisterType<LogAOP>();

            #region 层级注入

            #endregion
            #region 普通注入,与netcore本身提供netcore一致
            //builder.RegisterType<DemoServices>().As<IDemoServices>();
            //builder.RegisterType<DemoRepository>().As<IDemoRepository>();
            #endregion

            #region Load模式,用于批量注入,此处需要在API层加载引用或者是将services层和repository的dll文件生成到api层

            #region 加载引用注入
            通过反射加载services程序集
            //var assemblyServices = Assembly.Load("EptDemo2.Services");
            指定已扫描程序集中的类型注册为提供所有其实现的接口
            //builder.RegisterAssemblyTypes(assemblyServices).AsImplementedInterfaces();

            通过反射加载repository
            //var assemblyRepository = Assembly.Load("EpteDemo2.Repository");
            //builder.RegisterAssemblyTypes(assemblyRepository).AsImplementedInterfaces();
            #endregion

            #region 加载dll文件注入
            var basePath = AppContext.BaseDirectory;
            var servicesDllFile = Path.Combine(basePath, "EptDemo2.Services.dll");
            var assemblyServices = Assembly.LoadFile(servicesDllFile);
            builder.RegisterAssemblyTypes(assemblyServices).AsImplementedInterfaces()
                .EnableInterfaceInterceptors()引用Autofac.Extras.DynamicProxy;//对目标类型启用接口拦截。拦截器将被确定,通过在类或接口上截取属性, 或添加
                .InterceptedBy(typeof(LogAOP));


            var repositoryDllFile = Path.Combine(basePath, "EptDemo2.Repository.dll");
            var assemblyRepository = Assembly.LoadFile(repositoryDllFile);
            builder.RegisterAssemblyTypes(assemblyRepository).AsImplementedInterfaces();

            #endregion
            #endregion

            //将services填充Autofac容器生成器
            services.AddScoped<IDemoServices, DemoServices>();

            //将services填充Autofac容器生成器
            builder.Populate(services);

            //使用已创建的组件登记创建新容器
            var ApplicationContainer = builder.Build();

            //第三方IOC接管 core内置DI容器
            return new AutofacServiceProvider(ApplicationContainer);
            #endregion

进阶

在上一步骤中,LogAOP类解惑的方法仅仅是针对同步,如果你的services是异步的,这里获取不到,所以代码需要更新
如下:
在这里插入图片描述
大概代码如下

 /// <summary>
        /// 实例化IInterceptor唯一方法
        /// </summary>
        /// <param name="invocation">包含被拦截的方法信息</param>
        public void Intercept(IInvocation invocation)
        {
            //记录被拦截方法信息的日志信息
            var dataIntercept =
                //$"【当前操作用户】:{UserName}\r\n"+
                $"【当前执行方法】:{invocation.Method.Name}" +
                $"【携带的参数有】:{string.Join(",", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())} \r\n";

            try
            {
                //在被拦截的方法执行完毕后 继续执行当前方法
                invocation.Proceed();

                // 异步获取异常,先执行
                if (IsAsyncMethod(invocation.Method))
                {                   
                    if (invocation.Method.ReturnType == typeof(Task))
                    {               
                    //异步方法日志      
                    }
                    else
                    {
                    //同步方法日志
                    }
                }
                else//Task<TResult>
                {//同步1

                }
            }
            catch (Exception ex)//同步2
            {
                LogEx(ex, dataIntercept);
            }
        }
        //判断方法是否为异步方法
        private static bool IsAsyncMethod(MethodInfo method)
        {
            return (method.ReturnType == typeof(Task) ||
                 (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
                 );
        }
                private static bool IsAsyncMethod(MethodInfo method)
        {
            return (method.ReturnType == typeof(Task) ||
                 (method.ReturnType.IsGenericType && method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
                 );
        }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值