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

Ca_va

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<>))
                 );


————————————————
版权声明:本文为CSDN博主「Ca_va」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ca_va/article/details/106647047

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值