刚开始接触Remoting的时候,有点排斥,我都使用过webservice,wcf、以及rest。想一想,Remoting是不是过时了?由于公司前辈的缘故,公司的产品用的就是Remoting,那时候wcf出来,用的人估计不多,另外一方面,此处用Remoting还是很适合的,如果要改用wcf,未免感觉有点沉重。
关于Remoting的理论方面,的确好多文章都讲的是云里雾里。那么我们先看代码:
1 public interface IOfficeService 2 { 3 void Insert(Bibliography[] bibliographies); 4 5 IntPtr GetActiveDocumentWindowHandle(); 6 7 void Insert(string stream); 8 }
这是一个office插件提供的服务,核心是 Insert方法,实现word文档中插入题录的功能。
1 [Serializable] 2 public class OfficeServiceImplement : MarshalByRefObject , IOfficeService 3 { 4 public void Insert(Bibliography [] bibliographies) 5 { 6 OfficeServiceProxy.OnInsertReferences(bibliographies); 7 } 8 9 public IntPtr GetActiveDocumentWindowHandle() 10 { 11 return OfficeServiceProxy.OnGetActiveDocumentWindowHandle(); 12 } 13 14 public void Insert(string stream) 15 { 16 OfficeServiceProxy.OnInsertReferencesStream(stream); 17 } 18 }
这是word插件提供的服务器对象模型,这个对象因为继承了MarshalByRefObject,所以它可以跨应用程序域边界被引用。定义好了服务器对象模型,然后看看remoting的通讯机制:
1 channel = new HttpServerChannel(CHANNEL_NAME, GetEnablePort(), Provider); 2 RemotingConfiguration.RegisterWellKnownServiceType(typeof(OfficeServiceImplement), OBJECT_URI, WellKnownObjectMode.Singleton);
这两句代码,定义了服务器端的信道,而且公布了服务器端对象的地址,以及对象激活的方式。信道采用的是http,对象激活方式有两种:1、服务器端对象激活 2、客户端对象激活。此处采用服务器端对象激活中的singleton,我们可以理解为单例模式,也就是服务器端始终为一个对象,为客户端提供服务。 Provider是信息传输的方式,如二进制和xml传输。
1 public static SoapServerFormatterSinkProvider Provider = new SoapServerFormatterSinkProvider() 2 { 3 TypeFilterLevel = TypeFilterLevel.Full 4 };
显然程序中是采用soap格式,即xml方式传输。
1 public const string CHANNEL_NAME = "OfficeService"; 2 public const string OBJECT_URI = "OfficeService.rem";
以上这些工作都是服务器端定义服务,注册信道,那么客户端是如何调用呢?
1 if (WordService == null) 2 { 3 WordService = Activator.GetObject(typeof(IOfficeService), string.Format(OfficeService.ServiceUrl, ShareDataRW.OfficeAddinServicesPort)) as IOfficeService; 4 } 5 6 try 7 { 8 IntPtr window = WordService.GetActiveDocumentWindowHandle(); 9 10 if (Win32APIs.IsIconic(window) != IntPtr.Zero) 11 { 12 Win32APIs.ShowWindow(window, Win32APIs.WindowState.SW_SHOWNOACTIVATE); 13 } 14 15 Win32APIs.SetForegroundWindow(window); 16 }
这段代码是调用服务器端对象,获取word当前的活动窗口句柄,然后激活这个窗口。实现原理:通过指定服务地址,获取服务器对象的一个代理,所有的真实操作发生在服务器端,而客户端的这个代理是通过服务器对象序列化,发送到客户端生成的,在内存当中,对客户端来说是透明的,也就是说客户端不知道这个代理的存在。当客户端调用远程对象的一个方法时,这时候,代理会把请求参数,请求的方法等信息通过信道传送到服务器,服务器上的对象会执行相关方法,返回执行结果。
当然了remoting技术博大精深,我总结了下,把我的理解记录下来。