欢迎来到.net学习网

欢迎联系站长一起更新本网站!QQ:879621940

您当前所在位置:首页 »  .NET本质论第一卷:公共语言运行库教程 » 正文

本教程章节列表
最新评论

堆栈和消息转化

创建时间:2013年02月23日 22:54  阅读次数:(5515)
分享到:
上一节结束部分要求读者想象一个CLR提供的实用部件,用于创建请求消息。事实上,这个实用部件确实存在,并且CLR通过透明代理机制向程序员公开。

透明代理(transparent proxy,TP)是由CLR创建的一种特别对象,它的存在只是为了将方法调用转换成消息交换。透明代理总是隶属于一个名为真实代理(real proxy,RP)的兄弟对象。透明代理对象和真实代理对象之间是一一对应的关系。这种关系如图7.4所示。真实代理是一个派生于System.Runtime.Remoting.Proxises.RealProxy抽象基类型的类型的实例。你可以通过调用RealProxy.GetTransparentProxy方法从真实代理得到透明代理。另一种选择是通过在System.Runtime.Remoting.RemotingServices类上调用GetRealProxy静态方法。为此.你可以调用RemotingServices.IsTransparentProxy静态方法,测试一个任意对象引用。以确定它是指向一个透明代理.还是一个"真实对象”。
透明代理与真实代理

透明代理对象最终必须充当一个特定类型的实例,为此,RealProxy类型的构造函数需要它的派生类型传递一个System.Type对象.CLR将用它确定透明代理对象的有效(effective)类型,当isinst或castclass CIL操作码在透明代理上执行时,CLR将该调用路由到只是简单地查询真实代理的System.Type对象:
//isinst的伪代码,改进版
Bool isinst(object obj,System.Type testType){
//第1步:获取类型 用于测试!
Type targetType=null;
If(RemotingServices.IsTransparentProxy(obj1){
RealProxy rp=RemotingServices.GetRealProxy(obj);
targetType=rp.GetProxiedType();
}
Else
 targetType=obj.GetType();
//第2步,执行测试!
Return testType.IsAssignableFrom(targetType);
}

给定这个实现,考虑下面真实代码的实现
Public class MyProxy:RealProxy{
Public MyProxy():base(typeof(ICalculator)){}
//为了清晰起见,余下部分省略
}

给定这个代理实现,下面的代码将触发刚才描述的isinst实现:
MyProxy rp=new MyProxy();
Object tp=rp.GetTransparentProxy();
Icalculator calc=tp as Icalculator; //触发isinst

因为在MyProxy构造函数中,用于ICalculator的Systerm.Type对象被传递给了RealProxy构造函数,所以,GetProxiedType方法将返回一个类型对象,若标明true则说明它与ICalculaLor是兼容的。

真实代理的实现可以通过实现IRemotingTypeInfe接口,重写isinst和castclass的行为。这个接口有两个成员,主要的成员是CanCastTo方法:
Namespace System.Runtime.Remoting{
Public interface IremotingTypeInfo{
String TypeName(get;set;)
Bool CanCastTo(object object,System.Type testType);
}
}

当使用一个透明代理时,isinst和castclass的CLR实现都将查找这个接口;
//isinst的伪代码
Bool isinst(object obj,System.Type testType){
If(RemotingServices.IsTransparentProxy(obj)){
 RealProxy rp=RemotingServices.GetRealProxy(obj);
//专门用于IremotingTypeInfo
IremotingTypeInof rti=rp as IremotingTypeInfo;
 If(rti!=null)
return rti.CanCastTo(obj,test);
 else
  return test.IsAssignableFrom(rp.GetProxiedType());
}
 Else
   Return test.IsAssignableFrom(obj.GetType());
}

对于这个更为细化的实现,考虑下面的真实代码实现:
Public class MyProxy:RealProxy,IremotingTypeInfo{
Public MyProxy():base(typeof(ICalculator)){}
Public bool CanCastTo(object obj,Type testType){
 Return true; //危险!
}
//为了清晰起见,余下部分省略
}

在IRemotingTypeInfo.CanCastTo的这种实现下,无论请求类型是什么,在MyProxy的透明代理上的所有强制类型转换都将成功。其他实现将可能查看请求的类型,并使用合理的算法以确定强制类型转换失败与否。

一个程序获得透明代理的引用后,很可能这个程序将在代理对象上使用方法调用。当程序在透明代理对象上使用方法调用时,CLR将创建一个新的消息对象以表示这个调用。接着,CLR会将这个消息传递给真实代理用于处理。

我们期望真实代理产生另外一条消息,以表示调用的结果。然后,透明代理将使用第二条消息对这个调用的堆栈进行转化,透明地将结果传送给调用方。如果由真实代理返回的响应消息包含异常,透明代理将再次抛出这个异常,并再一次将结果传给调用方。

透明代理和真实代理之间的消息变换通过真实代理的Invoke办法发生。invoke方法接收一个请求消息作为其唯一的参数,并返同一个响应消息传达调用的结果。

Public abstract Imessage Invoke(Imessage request);

注意,在RealProxy类型中Invoke消息被标记为abstract。派生类型将实现该方法,并且提供一个产生响应消息的有意义的实现。前一节展示的ProcessMessage程序是这个过程的一个合理实现。

在透明代理对象上的方法调用,导致从基于堆栈处理的世界转变为基于消息处理的世界。在返回响应消息之前,真实代理的Invoke实现可能将消息分发给任何数量的处理节点。然而,为了传送调用片到一个实际对象,最终的处理节点归根结底都需要将请求消息转换成堆栈帧。CLR一般会提供个管道(plumbing)执行这种转换,这个管道被称为堆栈生成器接收器(stack builder sink),它通过RemotingServices.ExecuteMessage静态方法以可编程的方式公开。
Namespace System.Runtime.Remoting{
Public sealed class RemotingServices{
Public static Imessage
ExecuteMessage(MarshalByRefObject target,ImethodCallMessage request);
//为了清晰起见,余下部分省略
}
}

ExecuteMessage方法接收两个参数,一个对应方法请求的消息和一个将作为调用目标的对象引用。ExecuteMessage方法只是简单地为目标对象创建一个堆栈生成器接收器,并且发送一个消息给这个接收器。然后,堆栈生成器接收器处理底层的堆栈操作,并且调用实际的方法。当方法终止时,堆栈生成器接收器将把作为结果的堆栈帧转换成响应的消息,CLR用它作为ExecuteMessage调用的结果返回。

图7.5展示了透明代理和堆栈生成器接收器之间的关系。注意,堆栈生成器接收器从基于消息世界的处理转换为基于堆栈世界的处理,它通过透明代理高效地实现了这种反向转化。
使用代理截获r
来源:.net学习网
说明:所有来源为 .net学习网的文章均为原创,如有转载,请在转载处标注本页地址,谢谢!
【编辑:Wyf】

打赏

取消

感谢您的支持,我会做的更好!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

最新评论

共有评论0条
  • 暂无任何评论,请留下您对本文章的看法,共同参入讨论!
发表评论:
留言人:
内  容:
请输入问题 78+48=? 的结果(结果是:126)
结  果: