您的位置:首页 > 编程语言 > C#

C# 实现AOP的又一个方法[转]

2008-12-26 16:59 471 查看
Zezeze...怎么每次新的技术,好的思想都是外国人发现/发明的呢??难道中国人就想不到么?还是别的什么了........

在上一篇文章中,我介绍了使用DynamicProxy实现ExceptionLog的方法..其核心思想就是通过Reflection得到实际对象的接口类(其实得到的是接口的函数描述),从得到的接口类动态派生一个类,这个类的所有函数(从接口继承下来的)都被Hook了.此对象的所有函数调用都转向Invoke....

今天我来介绍一个比较简单的方法...其实这个东东在Steeven的帖子利用Attribute给C#实现AOP? 的评论就提到过的:P

我们一步一步的看这个东东的代码:P

public class Interposer :

System.Runtime.Remoting.Proxies.RealProxy,

System.Runtime.Remoting.IRemotingTypeInfo

好,上面的是类的声明,可以看出来,这个类是继承自RealProxy..呵呵,有没有想到什么? 对使用透明代理..是的....那实际的类得从MarshalByRefObject 继承么??还有,那个IRemotingTypeInfo是干什么的?? 呵呵,不用急,..我们再看后面的...

private Interposer( object target )

:

base( typeof( IInterposed ) )

{

m_target = target;

}

可以看出来,传给基类的参数是一个IInterposed的类型..

public interface IInterposed

{

object Target

{

get;

}

}

这是一个接口,没有任何方法,也没有实现任何属性.Zeze,又是问号??.不急,我们慢慢看后面的..

public override System.Runtime.Remoting.Messaging.IMessage Invoke( System.Runtime.Remoting.Messaging.IMessage message )

{

System.Runtime.Remoting.Messaging.IMethodCallMessage methodMessage =

new System.Runtime.Remoting.Messaging.MethodCallMessageWrapper( (System.Runtime.Remoting.Messaging.IMethodCallMessage) message );

System.Reflection.MethodBase method = methodMessage.MethodBase;

object returnValue = null;

// Handle IInterposed methods/properties here. Right now, there is

// only one property, so don't do any extensive checking to determine

// the method being invoked.

if ( method.DeclaringType == typeof( IInterposed ) )

{

returnValue = m_target;

}

else

{

try {

returnValue = method.Invoke( m_target, methodMessage.Args );

}

catch (System.Exception ex) {

returnValue = null;

}

}

System.Runtime.Remoting.Messaging.ReturnMessage returnMessage =

new System.Runtime.Remoting.Messaging.ReturnMessage( returnValue, methodMessage.Args, methodMessage.ArgCount, methodMessage.LogicalCallContext, methodMessage );

return returnMessage;

}

既然是通过透明代理实现的,那就得有Invoke函数,对,上面就是这个函数.

通过上面的代码,我们可以发现,实际上是调用对象m_target的函数,m_target就是构造函数中传进去的对象...

这就是生成透明代理的地方了:

public static object Wrap( object target )

{

Interposer interposer = new Interposer( target );

return interposer.GetTransparentProxy();

}

呵呵,到这里应该大部分都明白了,通过构造函数把实际的对象(你想操作的)传进去,得到透明代理,再通过透明代理进行调用..

咦,等等,传给RealProxy类的参数是IInterposed啊,不是我们实际的对象啊????

嗯,这就是"the key".因为我们这个类继承自IRemotingTypeInfo,实现这个接口后,我们可以把这个类型转化为任何类型(理论上,而且只是在编译时可以通过编译.如果在程序运行时把这个转成别的完全不一样的类,那会在调用函数时产生异常的).那么在调用强行转换后的类的函数时,通过透明代理,会把此对象的所有的函数调用信息(就算他自己没有这个函数,也会转发的,不会产生异常,如果没用透明代理,那就会像前面说的那样,产生异常)转发给Invoke函数,在这里,我们就调用实际的函数了.酱紫,我们就完成了函数调用的乾坤大挪移了:P...

好了,核心部分说完了.再看看Client调用方式:

public interface ISampleTarget

{

void DoSomething();

void DoException();

}

public interface INotImplemented

{

void Nothing();

}

public class SampleTarget : ISampleTarget,INotImplemented

{

public void DoSomething()

{

System.Console.WriteLine( "Doing Something." );

}

public void DoException( out int value )

{

throw new System.Exception("tt"); //测试异常

}

}

同样的,我们得从接口继承类...

SampleTarget realTarget = new SampleTarget();

ISampleTarget interposedTarget = (ISampleTarget) Interposer.Interposer.Wrap( realTarget );

interposedTarget.DoSomething();

object target = ( (Interposer.IInterposed) interposedTarget ).Target;

System.Console.WriteLine( "Interposed target type: {0}", target.GetType() );

INotImplemented target2 = (INotImplemented) interposedTarget;

try

{

target2.Nothing();

}

catch ( System.Exception e )

{

System.Console.WriteLine( "Expected exception: {0}", e );

}

从代码中红色的部分可以看出来,把Interposer对象转换成ISampleTarget(还记得我前面说得吗?? :) ),再调用函数....

呵呵,运行一下效果就完全出来了...

源文件从这个地方下载: Interposer

上述这个方法很轻便,比使用Emit的方式要简单的多...但是和DynamicProxy一样,还是不能Interrupt 构造函数...

看来我们可能还得等JGTM的大作了:P
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐