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

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

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

#region Method
private MethodInfomethod;
/// <summary>
/// Method被截获的目标方法
/// </summary>
public MethodInfo Method
{
get { return method;}
set {method = value;}
}
#endregion

#region Target
private object target;
/// <summary>
/// Target被截获的方法需要在哪个对象上调用。
/// </summary>
public object Target
{
get { return target;}
set {target = value;}
}
#endregion

#region Arguments
private object []arguments;
/// <summary>
/// Arguments调用被截获的方法的参数
/// </summary>
public object []Arguments
{
get { return arguments;}
set {arguments = value;}
}
#endregion

#region Invoke
/// <summary>
/// Invoke执行目标方法
/// </summary>
public object Invoke()
{
return this .method.Invoke( this .target, this .arguments);
}
#endregion
}

好,如何使用ESBasic.Emit来创建动态代理了?很简单,你只需要调用
public static TInterfaceCreateAopProxy < TInterface > ( object origin, IMethodInterceptor methodInterceptor, IAroundInterceptor aroundInterceptor)
如果不需要某种截获处理,对应的参数传入null即可。
举个例子,我们需要使用动态代理截获IComputer所有方法调用抛出的异常,并记录日志。IComputer定义如下:
public interface IComputer
{
int Add( int a, int b);
}

public class Computer: IComputer
{
public int Add( int a, int b)
{
throw new Exception( " TestException " );
return a + b;
}
}
我可以使用Around截获者来截获异常,所以我实现一个自己的IAroundInterceptor:
public class ExceprionAroundInterceptor : IAroundInterceptor
{
#region IAroundInterceptor成员
public object AroundCall( InterceptedMethod method)
{
try
{
return method.Invoke();
}
catch (Exceptionee)
{
ee
= ee;
// ..logException

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

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

下载 ESBasic.Emit.dll。













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


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论