离上次发表文章已经挺久的了,wcf这块确实挺烦人的,虽然用过几次,但是手写起来还是有点陌生,看了不少wcf的文章,终少有领悟,这里我捎带提起,更详细的我会推荐几篇不错文章供大家参考。
首先看下wcf大概包括些什么内容,这里是让大家有个清晰的纲领,不会深入介绍wcf,再说这一块也不是我这个凡人能给大家三言两语就能说明白的。
要使用wcf通信,首先要定义契约,我们再来看下wcf有哪些契约。
wcf的四种契约,我给他按使用的优先级拍个序吧,Service Contract是必不可少的也是必须的,Data Contract 也是常会用到的,用来定义通信结构体,但是没有这个,我们使用基础类型也是能完成通信,其次是Fualt Contract通信失败的契约,这个能告诉我们调用失败的详细信息也是很重要的,最后是Message Contract,这个是最不常用的了,本文也不会用到,有兴趣的可以自己找点资料看看。
好吧,引出我们今天的话题,客户端服务端通信的实现,关于通信设计模型大家可以看我第一篇的介绍,这里就不重复了。不管是客户端调用服务端还是服务端回调客户端,都是方法的调用,无非就是:(请求-回复)或者(请求),既然这样看下我定义的数据契约吧,定义的数据契约包括 请求数据契约 和 响应契约 两种。
[DataContract(Namespace = "http://www.cnblogs.com/guanglin/", Name = "Request")] public class Request { [DataMember] public string InstanceId { get; set; } [DataMember] public string MethodName { get; set; } [DataMember] public string[] ParamTypes { get; set; } [DataMember] public byte[] Parameters { get; set; } }
这个是请求契约其中MethodName为请求调用的方法名称,ParamType为请求调用的参数类型,Parameters为请求调用的参数,这里Parameters为什么使用byte[]数据类型呢?因为我们调用的方法参数的类型是不确定的,这里将参数序列化后传输,使用时再反序列化回来即可。这里还有个InstanceId是干什么用的呢,这跟我们的设计有关,我的客户端与服务端是基于页面创建的,这个InstanceId代表的是请求的页面服务或回调页面的唯一标识。
接下来看下响应契约,这个就简单了。
[DataContract(Namespace = "http://www.cnblogs.com/guanglin/", Name = "Response")] public class Response { [DataMember] public string InstanceId { get; set; } [DataMember] public byte[] Value { get; set; } }
回复契约只有唯一标识和返回值,并且返回值也使用byte[]传输,大家也能想到,这里返回值也将使用序列化传输。
好吧,数据契约定义完成了,下面来看下我们定义的服务契约与回调契约吧。服务契约是客户端调用服务的接口。
服务契约:
[ServiceContract(CallbackContract=typeof(ICoreCallbackService), SessionMode = SessionMode.Required, Namespace="GL")] public interface ICoreService { #region 连接操作 /// <summary> /// 连接到服务器,创建Session /// </summary> /// <param name="clientSessionInfo">客户端连接信息</param> /// <returns>连接的SessionId</returns> [OperationContract] [FaultContract(typeof(GLFaultContract))] string Connect(ClientConnectionInfo clientSessionInfo); /// <summary> /// 重新连接到服务器 /// </summary> /// <param name="sessionId">重新连接的SessionId</param> [OperationContract] [FaultContract(typeof(GLFaultContract))] void Reconnect(string sessionId); /// <summary> /// 断开与服务器 /// </summary> [OperationContract(IsTerminating = true)] [FaultContract(typeof(GLFaultContract))] void Disconnect(); #endregion #region 页面操作 /// <summary> /// 创建PageService实例返回实例id /// </summary> /// <param name="serviceTypeName">serviceTypeName</param> /// <returns>instanceId</returns> [OperationContract(IsOneWay = false)] [FaultContract(typeof(GLFaultContract))] string CreatePageService(string serviceTypeName); /// <summary> /// 销毁PageService实例 /// </summary> /// <param name="instanceId">instanceId</param> [OperationContract(IsOneWay = true)] void DestoryPageService(string instanceId); /// <summary> /// 调用一个页面服务方法 /// </summary> /// <param name="request">页面调用请求</param> /// <returns>页面调用回复</returns> [OperationContract] [FaultContract(typeof(GLFaultContract))] Response CallPageService(Request request); /// <summary> /// 单向调用一个页面服务方法 /// </summary> /// <param name="request">页面调用请求</param> [OperationContract(IsOneWay = true)] void OneWayCallPageService(Request request); /// <summary> /// 调用Session公共服务 /// </summary> /// <param name="request">服务请求参数</param> /// <returns>服务请求回复</returns> [OperationContract] [FaultContract(typeof(GLFaultContract))] Response CallService(Request request); /// <summary> /// 单向调用Session公共服务 /// </summary> /// <param name="request">服务请求参数</param> [OperationContract(IsOneWay = true)] void OneWayCallService(Request request); #endregion