WCF支持Stream操作尤其对于传递size过大的消息而言如要考虑传递消息的效率WCF推荐通过Stream进行操作然而WCF Stream操作规定了一些限制在我们编写相关程序时需要特别注意 绑定的限制 如果需要使用Stream操作可以使用的绑定只能是BasicHttpBindingNetTcpBinding以及NetNamedPipeBinding此外在使用Stream操作时不能使用Reliable Messaging如果考虑到消息安全则此方式是不可取的 对Stream对象的限制 要作为服务操作所传递的消息对象这样的对象必须是可序列化的遗憾的是FileStream类的定义却是不支持序列化的我们能够使用的Stream 对象包括StreamMemoryStream等使用Stream类对象是大多数Stream操作的首选一个有趣的现象是FileStream与Stream类型的转换例如在服务契约的操作中有如下的实现 public Stream TransferDocument(Document document) { FileStream stream = new FileStream (documentLocalPath FileModeOpen FileAccessRead); return stream; } 注意操作TransferDocument()的返回类型为Stream而方法的实现中返回的对象则为FileStream类型由于Stream类是FileStream类的父类这样的实现没有问题 然而在客户端调用该操作时却不能将操作的返回值赋给FileStream类型的对象如下所示 FileStream stream = m_serviceTransferDocument(doc); 此时获得的Stream对象则为null因而我们只能这样调用操作 Stream stream = m_serviceTransferDocument(doc); 但是还有一个奇怪的问题是WCF并不支持Stream对象Length属性的序列化也就是说在客户端我们不能使用服务操作返回的Stream对象的 Length属性诸如streamLength的调用会抛出NotSupportedException异常 TransferMode的限制 若要使用Stream操作必须修改绑定的TransferMode属性该属性的默认值为Buffered我们应该根据操作中WCF Stream对象的参数类型以决定TransferMode的值分别为StreamedStreamedRequest或者StreamedResponse MaxReceivedMessageSize的限制 MaxReceivedMessageSize属性的默认值为kb如果传递的Stream对象一旦超过了 MaxReceivedMessageSize属性的设置值则客户端在操作该对象时就会出现CommunicationException异常因此我们应根据实际需要设置MaxReceivedMessageSize的值MaxReceivedMessageSize属性的取值范围为 (IntMaxValue)如果设置值不在该范围之内则无法通过编译编程方式设置为 <binding …… maxReceivedMessageSize=/> 操作参数的限制 WCF Stream操作参数严格的限制它只允许这样的操作只能包含一个Stream对象这里所谓的一个WCF Stream对象是包含return对象out和ref对象在内的也就是说如下的操作定义都是错误的 void Transfer(Stream s Stream s); void Transfer(Stream s out Stream s); void Transfer(Stream s ref Stream s); Stream Transfer(Stream stream); 如果定义了这样的操作则会出现运行时错误 此外由于传输的WCF Stream对象较大可能会消耗过长的时间因而建议增大绑定的SendTimeout属性值例如设置为分钟编程方式设置为 bindingSendTimeout = TimeSpanFromMinutes(); 配置文件的设置方式为 <binding …… sendTimeout=::/> 注意对绑定的相关设置必须要求服务端与客户端的配置一致最佳实践是均通过配置文件进行设置例如在我的应用程序中是这样设置的 <basicHttpBinding> <binding name=DocumentExplorerServiceBinding sendTimeout=:: transferMode=Streamed messageEncoding=Text textEncoding=utf maxReceivedMessageSize=> </binding> </basicHttpBinding> |