• YZR之AOP


          说起面向切面编程(AOP),我会想起Asp.Net MVC的过滤器。微软提供了一些类给程序员在代码里面来完成切面处理。因为aop更多的是联系于权限,日志,登录等相关话题,在一个系统中,这些往往都是必须存在的,所以aop说起来也是很重要的存在着。前些日子在框架中实现了AOP方面的思想,写了几个类,在这里讨论一下。  

      先简单介绍一下几个类,在下文中再继续讲一下每个类都做了什么东西。

    namespace YZR.Interface
    {
        public interface IRWhere
        {
            string LogicName { get; set; }
    
            string WhereName { get; set; }
    
            string ActionName { get; set; }
    
            object ResultValue { get; set; }
        }
        public interface IRouteData
        {
            string TableName { get; set; }
    
            List<IRWhere> Wheres { get; set; }
    
            RAopEnum Action { get; set; }
        }
        public interface IAop
        {
            IRouteData Rdata { get; set; }
    
            void BeginAction();
    
            void EndAction();
        }
    }

      这里定义了几个接口类,IDataRoute描述的是面向切面编程中保存的数据,包括操作的表,条件以及动作。IAop描述的则是切面,这里写了BeginAction()和EndAction()两个切面。IRWhere则是描述条件。

    namespace YZR.Core
    {
        public class RAop : IAop
        {
            private IRouteData rdata;
    
            public IRouteData Rdata
            {
                get { return rdata; }
                set { rdata = value; }
            }
            public RAop()
            {
    
            }
            public RAop(RouteData _rdata)
            {
                this.rdata = _rdata;
            }
            public virtual void BeginAction()
            {
    
            }
    
            public virtual void EndAction()
            {
    
            }
    
    
        }
    }

      RAop实现了IAop接口,它将负责框架中对于切面处理被子类继承并重写BeginAction()和EndAction();

      这样我们自己定义自己的切面类时,只需要继承RAop类即可。

    namespace YZR.Logic
    {
        using YZR.Core;
        using YZR.Data;
        /// <summary>
        /// 编写你自己的Aop类 (比如权限)
        /// </summary>
        public class Aop:RAop
        {
            public Aop()
            { 
            
            }
            public  override void BeginAction()
            {
                RouteData rd = (RouteData)Rdata;   //用户操作的数据将会封装在RouteData,你可以通过Base.Rdata得到
    
                //TODO:通过RouteData进行逻辑处理
    
                #region 权限验证等处理
                #endregion
    
                base.BeginAction();
            }
    
            public  override void EndAction()
            {
                base.EndAction();
            }
        }
    }

      程序中只需要通过RouteData就可以得到切面中保存的信息,比如表,动作,条件等。

      例如有以下动作枚举:

     public enum RAopEnum
        {
            Select,
            SelectOne,
            Add,
            Update,
            Delete,
            None
        }

      编写完我们自己的Aop类之后,需要在应用程序中注册==>需要在AppStart.Filter(Instance)注册。

         protected void Application_Start(object sender, EventArgs e)
            {
                //初始化
                AppStart.AppStart.Init();
    
                //将你写的AOP类加载进来
                AppStart.AppStart.Fliter(new Aop());
            } 

    举个例子:  

    在我们的业务代码中实现一下代码:

                string drawAndregister = Request["adr"];
                string CookieTime = string.Empty;
                string CookieKey = string.Empty;
                string JsonStr = "{"State":0,"content":"24小时只能签到一次"}";
                IDataBase action = RUtility.Instance.GetDbUtility(TableName);
                action.ROpen();
                List<IRWhere> list = new List<IRWhere>();
                list.Add(new RWhere(" and ",Register.IsLuck,"=","0"));
                DataTable dt = action.Select(list);
                action.RClose();

    在我们自己编写的Aop类中就可以通过RouteData获得Select(list)的相关信息。

    那么底层是怎么实现的呢?

      从我们的全局文件开始讲起,看一下Filter()做了什么事情:

         public static void Fliter(object classObj)
            {
                aopContext.Add(classObj);
            }
        using YZR.Data;
        using YZR.Interface;
        public class aopContext
        {
    
            public static void Add(object classObj)
            {
                IAop iaop;
                try
                {
                    iaop = classObj as IAop;
                }
                catch (Exception ex)
                {
    
                    throw;
                }
                aopInstance.Add(iaop);
            }
        }

      从代码可以看出,最后是aopInstance.Add(new Aop());再来看一下aopInstance是什么东东。

    namespace YZR.Data
    {
        public class aopInstance
        {
            private static List<IAop> aopList=new List<IAop>();
    
            public static List<IAop> AopList
            {
                get { return aopInstance.aopList; }
                set { aopInstance.aopList = value; }
            }
    
            public static void Add(IAop iaop)
            {
                aopList.Add(iaop);
            }
        }
    }

      在这里aopInstance只是提供了一个List<T>来转载所有实现IAop接口的子类或者接口。

      哪你还是会说,你还是不知道到底为什么切面数据会保存到RouteData中去了,我们再来看RMotion(RAction)中做了什么,你就明白了。

           static RMotion()
            {
                rd = new RouteData();
    
            }
            private void AopInit()
            {
                List<IAop> list = aopInstance.AopList;
                foreach (IAop aop in list)
                {
                    aop.Rdata = rd;
                    aop.BeginAction();
                }
            }
            private void AopEnd()
            {
                List<IAop> list = aopInstance.AopList;
                foreach (IAop aop in list)
                {
                    aop.EndAction();
                }
            }
           public DataTable Select(List<IRWhere> whereList)
            {
                rd.Action = RAopEnum.Select;
                rd.TableName = tableName;
                rd.Wheres = whereList;
                rd.ColNames = "*";
                AopInit();
    
                StringBuilder sb = new StringBuilder();
                StringBuilder sbWhere = new StringBuilder();
                if (!whereList.Any())
                {
                    sb.AppendFormat("select * from {0} ", tableName);
                }
                else
                {
                    for (int i = 0; i < whereList.Count; i++)
                    {
                        IRWhere where = whereList[i];
                        sbWhere.AppendFormat(" " + where.LogicName + " " + where.WhereName + " " + where.ActionName + " '" + where.ResultValue + "' ");
    
                    }
                    sb.AppendFormat("select * from {0}  where 1=1 {1} ", tableName, sbWhere.ToString());
                }
                //SqlConnection conn = DbAction.getConn();
                if (ston == null)//返回一个新的SqlCommand,不含事务
                {
                    com = getCommand(sb.ToString());
                }
                else
                {
                    //若ston不为null,即含有事务,com已经创建
                    com.CommandText = sb.ToString();
                }
                //conn.Open();
                SqlDataReader dr = com.ExecuteReader();
                DataTable dt = new DataTable();
                int fieldcout = dr.FieldCount;
                if (dr.FieldCount > 0)
                {
                    for (int i = 0; i < dr.FieldCount; i++)
                    {
                        DataColumn dc = new DataColumn(dr.GetName(i), dr.GetFieldType(i));
                        dt.Columns.Add(dc);
                    }
                    object[] rowobject = new object[dr.FieldCount];
                    while (dr.Read())
                    {
                        dr.GetValues(rowobject);
                        dt.LoadDataRow(rowobject, true);
                    }
                }
                dr.Close(); ;
                // conn.Close();
                AopEnd();
                
                return dt;
            }

      在YZR.Data中调用Select()方法的时候,在AopInit()会使用aopInstance对象的BeginAction(),在AopEnd()中调用aopInstance对象的EndAction();而且在执行BeginAction()或者EndAction()之前会将切面数据保存到RouteData类型变量中,这样在业务逻辑层中就可以通过RouteData得到所有切面数据。

      通过RouteData提供出来的信息,程序代码可以知道现在要执行的是什么任务或动作,这样在Aop类中你可以在BeginAction()处理动作完成之前要做的一些判断或者操作,在EndAction()处理动作操作完成之后的一些操作或者完成信息。

  • 相关阅读:
    Java 泛型的使用
    IDEA 2017.2.2 环境下使用JUnit
    Tomcat的下载安装及使用
    JavaScript基础知识(二)
    JavaScript基础知识(一)
    CSS3基础(4)——CSS3 渲染属性
    CSS3基础(3)——CSS3 布局属性全接触
    CSS3基础(2)—— 文字与字体相关样式、盒子类型、背景与边框相关样式、变形处理、动画功能
    CSS3 基础(1)——选择器详解
    CSS基础学习笔记
  • 原文地址:https://www.cnblogs.com/Francis-YZR/p/5092043.html
Copyright © 2020-2023  润新知