一.自定义AOP的实现方式
1、使用ContextAttribute和ContextBoundObject来对对象的方法进行拦截。关于ContextAttribute的具体使用方法,读者可以参考MSDN等相关资料。
2、使用Proxy模式。这也是本文的实现方法。
二、直接上代码
1、首先定义了抽象类AspectObject,所有需要AOP管理的类,都必须从这个类继承下来。这个类的定义如下:
public abstract class AspectObject : ContextBoundObject
之所以定义这个类,并且让它继承ContextBoundObject,其原因是因为,.Net能够拦截任何直接从ContextBoundObject派生的类(包括子类的子类);另外定义成abstract,目的是为了将来可能的扩充性,我们据此可以对其在运行时刻的行为做出一些自定义的控制,请看如下代码:
public class BusinessOperation: AspectObject
{
……
}
2、AspectManagedAttribute
这是一个非常关键的类,其作用是拦截类的构造函数。如前所述,当你在执行诸如:
BusinessOperation business = new BusinessOperation();
你实际上得到的不是BusinessOperation,而是BusinessOperation的一个代理,正因为如此,我们才能够在执行这个对象的方法的时候,把他们拦截下来,插入我们自己的代码。
此类代码如下:
[AttributeUsage(AttributeTargets.Class)] //由于这个特性允许标识在类上,所在需要加上[AttributeUsage(AttributeTargets.Class)]
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.Infrastructure)]
public class AspectManagedAttribute : ProxyAttribute
{
private bool aspectManaged;
private string[] aspectsType;
public AspectManagedAttribute(bool AspectManaged, string AspectType)
{
aspectManaged = AspectManaged;
aspectsType = AspectType.Split(',');
}
public override MarshalByRefObject CreateInstance(Type serverType)
{
MarshalByRefObject mobj= base.CreateInstance(serverType);
if(aspectManaged) //aspectManaged指明该类是否接受Aspect管理
{
RealProxy realProxy = new AspectProxy(serverType, mobj, aspectsType);
MarshalByRefObject retobj = realProxy.GetTransparentProxy() as MarshalByRefObject;
return retobj;
}
else
{
return mobj;
}
}
}
重写ProxyAttribute的方法:MarshalByRefObject CreateInstance(Type serverType)。根据不同的AspectManagedType创建不同的自定义代理类。
当我们拦截构造函数的时候,就会执行这个方法,在这里,我们可以对被拦截的构造函数的类进行一些处理,生成被实例化的类的代理。
此类定义完之后,在BusinessOperation类上就可加入此属性类
[AspectManaged(true, "AspectClient.SecondAspect, AspectClient.SecurityAspect")]
public class BusinessOperation: AspectObject
{
}
3、AspectProxy
需要继承RealProxy,它提供代理的基本功能。
当被代理的某个对象的方法执行时,就会被代理所拦截,代理会执行Invoke方法。
public class AspectProxy : RealProxy
{
MarshalByRefObject target = null;
string[] _aspectsType = null;
/// <summary>
/// 默认构造函数
/// </summary>
public AspectProxy() : base()
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="myType">被代理的类的类型</param>
public AspectProxy(Type type) : base(type)
{
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="myType">被代理的类的类型</param>
/// <param name="obj">被代理的对象</param>
public AspectProxy(Type type, MarshalByRefObject obj, string[] aspectsType) : base(type)
{
target = obj;
_aspectsType = aspectsType;
}
public override IMessage Invoke(IMessage message)
{
IMessage Msg;
PreProcess(message); //被拦截方法执行前进行处理
if(message is IConstructionCallMessage) //如果message是构造函数
{
IConstructionCallMessage constructCallMsg = message as IConstructionCallMessage;
RemotingServices.GetRealProxy(target).InitializeServerObject(constructCallMsg);
ObjRef oRef = RemotingServices.Marshal(target);
RemotingServices.Unmarshal(oRef);
Msg = EnterpriseServicesHelper.CreateConstructionReturnMessage(constructCallMsg ,(MarshalByRefObject)this.GetTransparentProxy());
}
else if(message is IMethodCallMessage)
{
IMethodCallMessage callMsg = message as IMethodCallMessage;
retMsg = RemotingServices.ExecuteMessage(target, callMsg );
}
PostProcess(msg); //被拦截方法执行后进行处理
return Msg;
}
/// <summary>
/// 被拦截方法执行前进行处理,AspectActionPosition是个枚举包含三个元素,Befor,After,Both
/// </summary>
/// <param name="message">IMessage,包含有关方法调用的信息</param>
private void PreProcess(IMessage message)
{
IAspect[] aspectBefore = AspectsManager.GetAspect(message, AspectActionPosition.Before, _aspectsType);
if((aspectBefore != null) && (aspectBefore.Length > 0))
{
for(int i = 0; i < aspectBefore.Length; i++)
{
aspectBefore[i].PreProcess(message);
}
}
}
/// <summary>
/// 被拦截方法执行后进行处理
/// </summary>
/// <param name="message">IMessage,包含有关方法调用的信息</param>
private void PostProcess(IMessage message)
{
IAspect[] aspectAfter = AspectsManager.GetAspect(message, AspectActionPosition.After, _aspectsType);
if((aspectAfter != null) && (aspectAfter.Length > 0))
{
for(int i = 0; i < aspectBefore.Length; i++)
{
aspectAfter[i].PostProcess(message);
}
}
}
}
4、辅助的接口和类
上面一些主要类都已介绍完毕.另外还一些辅助的接口和类
public interface IAspect
{
/// <summary>
/// 在被拦截的方法执行前执行的方法
/// </summary>
/// <param name="Message">IMessage,包含有关方法调用的信息</param>
void PreProcess(IMessage Message);
/// <summary>
/// 在被拦截的方法执行后执行的方法
/// </summary>
/// <param name="Message">IMessage,包含有关方法调用的信息</param>
void PostProcess(IMessage Message);
}
所有的拦截业务都要继承这个接口(当然这个接口可以再扩展).
例如定义一个SecurityAspect类
public class SecurityAspect : IAspect
{
public void PreProcess()
{
if(!Security.CheckRight(......))
{
throw new SecurityException("你没有权限!");
}
}
public void PostProcess()
{
………
}
}
public class AspectsManager //Aspects管理类
{
//这里面主要用到的是GetAspect,返回IAspect数组.
//根据Config文件中的配置以及[AspectManaged(true, "AspectClient.SecondAspect, AspectClient.SecurityAspect")]定义获取
//每个需要拦截的业务类的IAspect集合.
}
下面是配置文件中的配置:
<Websharp.Aspects>
<Aspect type="AspectClient.SecurityAspect,AspectClient" deploy-model="Singleton" pointcut-type="Method" action-position="Before" match="*,*" />
<Aspect type="AspectClient.LogAspect,AspectClient" deploy-model="Singleton" pointcut-type="Method" action-position="After" match="*,*" />
</Websharp.Aspects>
自定义AOP的实现方式就差不多写完了,可能个人技术水平,只能写到这样了.希望有问题请给出指正,大家共同探讨.