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()处理动作操作完成之后的一些操作或者完成信息。

你可能感兴趣的:(YZR之AOP)