使用动态代理,提高工作效率

动态代理的一个最主要的应用场合就是实现AOP - 截获方法调用,加入自己的预处理、后处理或Around处理。
我在ESBasic.Emit中实现了对这些截获的支持。
首先,介绍两个截获者:
///<summary>
///IMethodInterceptor对方法进行截获并加入预处理和后处理。
///</summary>
publicinterfaceIMethodInterceptor
{
voidPreProcess(InterceptedMethodmethod);

voidPostProcess(InterceptedMethodmethod,objectreturnVal);
}
IMethodInterceptor 很容易理解,用于为截获插入预处理、后处理。这个非常容易理解。
///<summary>
///IAroundInterceptor对方法进行Around截获处理。注意,必须要触发目标方法的调用。
///</summary>
publicinterfaceIAroundInterceptor
{
objectAroundCall(InterceptedMethodmethod);
}
Around处理由IAroundInterceptor完成。什么是Around处理了?比如,我们想捕获目标方法的异常,需要使用TryCatch将目标方法Around起来,这就是Around处理的一个例子。
在上面的接口方法中都有一个参数InterceptedMethod,它封装了被截获的目标方法的基本信息。
publicsealedclassInterceptedMethod
{
#regionCtor
publicInterceptedMethod(){}
publicInterceptedMethod(object_target,MethodInfo_method,object[]paras)
{
this.target=_target;
this.method=_method;
this.arguments=paras;
}
#endregion

#regionMethod
privateMethodInfomethod;
///<summary>
///Method被截获的目标方法
///</summary>
publicMethodInfoMethod
{
get{returnmethod;}
set{method=value;}
}
#endregion

#regionTarget
privateobjecttarget;
///<summary>
///Target被截获的方法需要在哪个对象上调用。
///</summary>
publicobjectTarget
{
get{returntarget;}
set{target=value;}
}
#endregion

#regionArguments
privateobject[]arguments;
///<summary>
///Arguments调用被截获的方法的参数
///</summary>
publicobject[]Arguments
{
get{returnarguments;}
set{arguments=value;}
}
#endregion

#regionInvoke
///<summary>
///Invoke执行目标方法
///</summary>
publicobjectInvoke()
{
returnthis.method.Invoke(this.target,this.arguments);
}
#endregion
}

好,如何使用ESBasic.Emit来创建动态代理了?很简单,你只需要调用
publicstaticTInterfaceCreateAopProxy<TInterface>(objectorigin,IMethodInterceptormethodInterceptor,IAroundInterceptoraroundInterceptor)
如果不需要某种截获处理,对应的参数传入null即可。
举个例子,我们需要使用动态代理截获IComputer所有方法调用抛出的异常,并记录日志。IComputer定义如下:
publicinterfaceIComputer
{
intAdd(inta,intb);
}

publicclassComputer:IComputer
{
publicintAdd(inta,intb)
{
thrownewException("TestException");
returna+b;
}
}
我可以使用Around截获者来截获异常,所以我实现一个自己的IAroundInterceptor
publicclassExceprionAroundInterceptor:IAroundInterceptor
{
#regionIAroundInterceptor成员
publicobjectAroundCall(InterceptedMethodmethod)
{
try
{
returnmethod.Invoke();
}
catch(Exceptionee)
{
ee
=ee;
//..logException

throw;
}
}
#endregion
}
现在,我们可以这样获得针对IComputer的动态代理的引用:
IComputerproxy=ESBasic.Emit.Application.DynamicProxyFactory.CreateAopProxy<IComputer>(newComputer(),null,newExceprionAroundInterceptor());
proxy.Add(
1,2);
这样就ok了,Add方法抛出的异常会被ExceprionAroundInterceptor截获。

最后,提醒一下,如果你让Computer不从IComputer继承,运行结果也一样。你应该已经看到DynamicProxyFactory.CreateAopProxy方法的第一个参数是object类型,而不是泛型T,这说明只要对应的object包含了和目标接口一样的方法(签名完全一致)就可以 -- 这就是所谓的“换脸”能力,可以在这里看到更详细的说明。
由于动态代理是使用Emit发射实现,所以效率上来说,和你手写的代码是没有区别的。

下载 ESBasic.Emit.dll。













阅读更多

没有更多推荐了,返回首页