这个消息接收器将值52插入到名为mykey的逻辑的调用上下文插槽接着,下游的消息接收器能够找到这个数据,如下所示:
public IMessage SYncProcessMessage(IMessage request){
IMethodMessage method=(IMethodMessage)request ;
//从调用上下文中取到数据
object val=method.LogicalCallContext.GetData(“mykey”) ;
int mykey=0 ;
if(val !=null){
mykey=(int)val;
method.LogicalClaaContext.FreeNamedDataSlot(“mykey”);
}
return next.SyncProcessMessage(request);
}
这个实现只是简单地获取了在插槽mykey中的值,并且把它存储在一个局部变量中。注意这个实现检查了该值是否实际是存在的。另外,在取得这个值之后,接着它便释放了在调用上下文中的插槽,这防止了下游的链接看到这个值。这一步是可选的;否则的话插槽将无限期地保持占用状态。
当调用方或被调用方访问调用上下文时,有关它的更有趣的应用就会发生。这种功能是通过System.Runtime.Remoting.Messaging.CallContext类型公开的。这个类型公开了三个静态方法(GetData、SetData和FreeNamedDataSloL),用于当前线程操纵隐式的调用上下文。透明代理和堆栈生成器接收器都使用隐式的调用上下文,用于保持隐式上下文与消息中用到的显式LogicalCallContext属性同步。
下面的客户端代码手工生成了调用上下文,其在功能上与前面列举的SyncProcessMessage是一样的:
using System.Runtime.Remoting.Messaging;
class App{
static void Main(){
//产生一个新的上下文绑定对象
Icalculator calc=new MyCalc3();
//在隐式的插槽”mykey”中插入52
CallContext.SetData(“mykey”,52);
//发出调用---对于这个调用,TP将建立LogicalCallContext
double val=calc.Add(3,2);
}
}
相似地,目标方法也能访问这个调用上下文:
using System.Runtime.Remoting.Messaging;
public class MyCalc3:ContextBoundObject,Icalculator{
//从隐式的插槽”mykey”中获取数据
int n=0;
object val=CallContext.GetData(“mykey”);
if(val!=null){
n=(int)val;
CallContext.FreeNamedDataSlot(“mykey”);
}
//处理调用(使用来自调用上下文的数据)
return x+y+n;
}
这个目标方法并不关心调用上下文是由调用方生成,还是由一个中间消息接收器生成。
你还可以为一个调用发送调用上下文,作为响应消息的一部分。如果目标方法调用了CallContext.SetData,堆栈生成器接收器将使用这个信息生成响应消息,这使得任何调用上下文对于上游的消息接收器和最初的调用方都是可用的。
调用上下文通常被绑定到一个特定的线程。然而,一些消息接收器可能引发一个线程开关,甚至可能通过网络发送消息的一个序列化版本给远程应用程序。在一般情况下,调用上下文不会跨物理线程边界而传播。然而,你能够在一个接一个插槽(slot by slot)的基础上改变这种限制。如果存储在插槽中的数据实现了System.Runtime.Remoting.ILogicalThread
Affinative接口,那么对于跳越线程、跳越应用程序、跳越进程或跳越机器边界的消息接收器来说,需要在这个接收链中传播(propagate) 另一个节点的插槽。ILogicalThreadAffinative接口没有方法:从本质上讲,它只是用来通知消息管道哪个调用上下文插槽需要传播。不过,假如你只是想传播一个基本数据类型,则需要编写一个包装类实现ILogicalThread Affinative接口,并且把这个基本数据类型作为一个公有字段。誰孴S