您的位置:首页 > 运维架构

YZR之AOP

2015-12-31 16:07 429 查看
说起面向切面编程(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()处理动作操作完成之后的一些操作或者完成信息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: