Fork me on GitHub

AOP实战(1)

AOP在MVC中有广泛的应用 如:IActionFilter、 IAuthenticationFilter、 IAuthorizationFilter、IExceptionFilter、IResultFilter

熟悉MVC的人对这些过滤器已经是运用自如了

下面说下在项目中如何监控自己自定义类的方法 或者接口,本文结合Autofac 做一些介绍:

这里需要几个Nuget包:

Autofac;

Castle.DynamicProxy;

Autofac.Extras.DynamicProxy;

DynamicProxy 可以监控接口以及类这里对监控接口做了一个例子:

/// <summary>
    /// liyouming  Add  20170914 AOP 拦截器
    /// </summary>

    public class LoggerAttribute : IInterceptor
    {

        private IDAL_TbSysOperatorLog _operatorLogs;


        public LoggerAttribute(IDAL_TbSysOperatorLog operatorLogs)
        {
            _operatorLogs = operatorLogs;


        }
        public void Intercept(IInvocation invocation)
        {

            var LogMethod = invocation.Method.GetCustomAttribute(typeof(LogMethodAttribute), false) as LogMethodAttribute;
            if (LogMethod != null)
            {
                var userinfo = HttpContext.Current.User as ClaimsPrincipal;
                string name = invocation.Method.Name;
                var mappedParameters = MapParameters(invocation.Arguments, invocation.Method.GetParameters())
                .ToDictionary(x => x.Key, x => x.Value.ToString());
                string parameters = JsonConvert.SerializeObject(mappedParameters);
                Stopwatch watch = Stopwatch.StartNew();
                invocation.Proceed();
                string exectime = watch.ElapsedMilliseconds.ToString();
                string returnValue = JsonConvert.SerializeObject(invocation.ReturnValue);
                _operatorLogs.Insert_TbSysOperatorLogAsync(new TbSysOperatorLog { CreateID = userinfo.FindFirst("sub").Value, CreateName = userinfo.FindFirst("user_name").Value, OperatorResult = returnValue, ClassMoudle = invocation.InvocationTarget.ToString(), OperatorMethod = name, OperatorParameters = parameters, ExecTime = exectime, Description = LogMethod.Option, IP = HttpContext.Current.Request.UserHostAddress });
            }
        }
        public IEnumerable<KeyValuePair<string, object>> MapParameters(object[] arguments, ParameterInfo[] getParameters)
        {
            for (int i = 0; i < arguments.Length; i++)
            {
                var obj = JsonConvert.SerializeObject(arguments[i]);
                yield return new KeyValuePair<string, object>(getParameters[i].Name, obj);

            }
        }
    }

上述代码是结合 Owin中间件授权 加上 Autofac注入

在注入LoggerAttribute之前首先要注入相关的接口服务  IDAL_TbSysOperatorLog 是我的操作日志服务 ,在构造函数中加入对 IDAL_TbSysOperatorLog的依赖,然后结合Owin中间件中的信息,获取对应操作人员,之前也被AOP中如何获取日志操作人犯愁,后面发现这样做对了

Autofac注入相关代码:

  builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
                         .Where(t => t.GetCustomAttribute<DependencyRegisterAttribute>() != null)
                         .AsImplementedInterfaces().EnableInterfaceInterceptors()
                         .InstancePerLifetimeScope();
            builder.RegisterType<LoggerAttribute>().InstancePerLifetimeScope();
            builder.RegisterType<ExecTimeAttribute>().InstancePerLifetimeScope();

.EnableInterfaceInterceptors() 这是允许设置监控接口

.EnableClassInterceptors() 是允许设置监控类

根据实际项目情况设置

builder.RegisterType<LoggerAttribute>().InstancePerLifetimeScope();

//注册我们自定义的监控方法,实现IInterceptor就行了 

这里设置监控的方法,类名称、参数值、执行时间、ip、方法返回值 等等

 因为这里IInterceptor属性只能定义 类或者接口 那么对于接口或者类中的所有方法都会监控,怎么去除掉不必要的方法监控

自定义一个方法属性:设置属性只能用在方法上,这样含有该属性的方法就能写日志,日志一般会有描述(如:业务功能描述) 所以这里我加入了一个Option 

 [AttributeUsage(AttributeTargets.Method)]
    public class LogMethodAttribute : Attribute
    {
        private string _option;
        public LogMethodAttribute()
        {
            _option = "";
        }
        public LogMethodAttribute(string Option)
        {

            _option = Option;
        }

        public string Option
        {
            get
            {

                return _option;
            }
            set {
                _option = value;
            }

        }
    }

 

下面看看接口中的写法:
 [Intercept(typeof(LoggerAttribute))]
    public interface IBLL_TESTServices
    {

        [LogMethod(Option = "添加测试用例")]
        Task<OperationResult> AddTEST(TESTModel model);


        List<dynamic> GetPremission(string guid);
    }

 

接口中有两个方法,这里只监控了 AddTEST 方法 并产生操作日志,这里我里面的操作日志最好用异步

接下来测试下:查看数据库中数据

 

至此依然搞定,AOP 使我的代码耦合性降低了,我们不用在每个方法中去写很多方法,面向切面编程只需要写属性就ok,而且监控方法名 参数值  执行结果  想想都觉得棒~~

 

 







 

posted @ 2017-09-15 14:41  龙码精神  阅读(546)  评论(0编辑  收藏  举报