Remoting是NET平台下比较成熟高效的分布式技术,我们习惯采用传统的远程 调用的方式使用Remoting。在客户端所在的Application Domain,我们通过 Proxy(Transparent Proxy)远程地跨Application Domain调用一个方法。当来 自Client端的调用请求通过Proxy到达Server端所在的Application Domain后, Remoting Infrastructure在Server 端激活(Activate)相应的远程对象(一个 继承子System.MarshalByRefObject类对象)——这里仅仅以服务端 激活对象(Server Activated Object——SAO),然后再Server端执行相应的操作后把Result传递给Proxy,并最终到达Client。这是一种典型的 Request/Response的调用方式。
我之所以一直比较推崇在.NET平台下使 用Remoting而非XML Web Service是因为我觉得.NET Remoting是一种比较成熟的 分布式技术。它自身提供了XML Web Service很多不具备的特性,其中对双向通 信的支持就是一个很好的体现。
相对于典型的Request/Response的消息 交换模式(Message Exchange Pattern——MEP),双向通信实质上 是采用的Duplex的MEP。也就是说,Server端在执行操作的时候,可以回调 (Callback)Client端的操作(这个操作时再Client端的Application Domain中 执行的)。
现在我们来看如何一步一步实现在Remoting环境下的双向通 信。在下面的Sample中,我们的逻辑是:调用一个数学计算的远程调用,除了传 递相应的操作数之外,我们还传递一个对象,这个对象可以在Server端中回调 (Callback) 把运算结果在Client端显示出来。
Step1:构建整个 Solution的整体构架。
Artech.DuplexRemoting.Contract:Class Library Project,定义远程对象(Remote Object)和Callback对象的Contract (Interface)。实际上,站在Server端的角度上看,Callback的操作是在 Client端的Application Domain中执行的,所以从本质上讲, Callback对象是 Server端的远程对象。
之所以定义这样一个Contract Project,其目的 主要有以下几点:
1.如果没有把远程对象的Interface,对已某一个需 要调用这个远程对象的Client来说,它必须引用远程对象本身。从安全的角度考 虑,Server向Client过多暴露了操作的实现逻辑。如果我们把远程操作的 Contract提取出来,Client只要引用这个Interface就可以了。
2.一般 来说,远程对象的Contract相对时静态的(static),而业务逻辑的实现则是经 常 变化的。因为Client只需要了解的是远程对象的Contract,所在无论Server 端对远程对象的实现作了多大的变动,对不回对Client产生任何影响。
Artech.DuplexRemoting.Remoting:Class Library Project,定义远程 对象本身。由于远程对象必须实现上边定义的Contract。所以需要引用 Artech.DuplexRemoting.Contract。
Artech.DuplexRemoting.Hosting: Console Application Project,以Self-Host的方式Host Remoting。引用 Artech.DuplexRemoting.Remoting。
Artech.DuplexRemoting.Client: Console Application Project,引用Artech.DuplexRemoting.Contract。
Step 2 在Artech.DuplexRemoting.Contract中定义 Contract
IDuplexCalculator.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Artech.DuplexRemoting.Contract
{
public interface IDuplexCalculator
{
void Add(double x, double y, ICalculatorCallback callback);
}
}
ICalculatorCallback.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace Artech.DuplexRemoting.Contract
{
public interface ICalculatorCallback
{
void ShowResult (double x, double y, double result);
}
}