日志 20071207(CAB,Data Transfer in WCF)

1.自己用CAB的时候,由于对CAB底层机制尚未洞悉,有些地方用的总感觉别扭。比如,如果我希望用客户端保存(PersistenceService)的数据来初始化启动界面中的SmartPart控件,按理说我应该在控件的InitializeComponent()中访问控件所在的WorkItem,然后使用WorkItem调用持久化服务。但由于我是采用依赖注入的方式通过属性向SmartPart传入其所属WorkItem的引用,如代码段1:
 1//代码段1
 2
 3private BidListWorkItem parentWorkItem;
 4[ServiceDependency]
 5public BidListWorkItem ParentWorkItem
 6{
 7    set 
 8    parentWorkItem = value;
 9    }

10}
这个属性被注入的时间晚于控件的InitializeComponent()被调用的时间,所以前面所述方案不成立。目前我采用的方法列在代码段2,感觉上不好,虽然逻辑上不错但结构恶心。等自己把WorkItem和SmartPart之间初始化的整个流程都搞清楚了,再来重构吧。
 1//代码段2
 2
 3private BidListWorkItem parentWorkItem;
 4[ServiceDependency]
 5public BidListWorkItem ParentWorkItem
 6{
 7    set 
 8    parentWorkItem = value;
 9    //放在这里进行调用,实在有些别扭
10    this.InitializeByWorkItem();
11    }

12}

13
14private void InitializeByWorkItem()
15{
16    string savePath = parentWorkItem.PathForBidTopicFiles;
17    if (savePath != null)
18    {
19    this.textBoxPath.Text = savePath;
20    }

21}

2.对于大文件的传输,现在脑子里有几个基本的概念:
 (1)要用Streamed的方式,不要用Buffered的方式
 (2)要使用二进制格式的原生信息,不要使用Base64进行信息的文本化处理
 (3)WCF本身考虑的是怎么对信息作编码,通过什么样的协议传过来。但续传本身的一些功能(比如把已经传过来的内容先一部分得保存起来等)可能需要自己去考虑它的实现方式。

3.如果使用MTOM作为一个binding的Encode方式,如代码段3:
<!--代码段3-->

<bindings>
    
<wsHttpBinding>
        
<binding name="ExampleBinding" messageEncoding="Mtom"/>
    
</wsHttpBinding>
</bindings>
对于你传送的二进制流(byte[]),不管这个传送数据是通过如代码段4这样的方式以DataContract显示指定的,还是在一个Operation里面作为参数返回值,MTOM都是按照相同的策略对其进行处理:如果数据量够大(大到了可以负担MIME头等的开销),则使用二进制的MIME进行消息传送;否则依然采用Base64编码。
//代码段4

[DataContract]
class MyData
{
    [DataMember]
    
byte[] binaryBuffer;
}
 
另外,如果自己理解的不错的话,MTOM考虑的只是消息内容的编码方式,但至于消息是按照Streamed还是Buffered的方式去发送和接收,与之无关。

4.使用Streamed的方式去发送消息,有几个明显的限制:
(1)无法对消息体进行签名。这是当然的,因为内存里不再缓存整个消息了。
(2)由于无法签名,所以一些依赖于签名的加密手段就不能使用了。
(3)难以支持整个消息的重发,因而也就无法保证一个可靠的连接(reliable session)
正因为有这些限制,所以WCF中的很多默认的Binding是不支持这种Streamed的方式的,只有下面三种绑定可以:BasicHttpBinding, NetTcpBinding, NetNamedPipeBinding。

5.对于TransferMode这个枚举值,第一次在MSDN的时候可是把俺为难坏了,啃了半天英文也没搞清楚到底哪种环境适合用什么,直到后来看到代码段5例子(我已添加注释):

 1//代码段5
 2
 3[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
 4public interface IStreamedService
 5{
 6    //传入和返回参数都是Stream,因此TransforMode应设为Streamed
 7    [OperationContract]
 8    Stream Echo(Stream data);
 9    //只有返回值是Stream,因此TransforMode应设为StreamedResponse
10    [OperationContract]
11    Stream RequestInfo(string query);
12    //这是一个OneWay的Operation,且传入参数为Stream,因此TransforMode应设为StreamedRequest
13    [OperationContract(OneWay=true)]
14    void ProvideInfo(Stream data);
15}

16
17/*
18 * 如果Echo或者ProvideInfo还有另一个输入参数,传输将自动切换回Buffered的模式。这也是Streamed传输模式的一个大的特点。
19 */

另外,这也纠正了我以前的一个误区。我以前认为ServiceContract和Binding是一一对应的,或者说,我认为如代码段6这样的配置中的contract属性只能指向一个ServiceContract,看来我是错的(还需以后的验证)。

<!--代码段6-->
<endpoint address="http://service.eally.com.cn/GEAWCFServiceHost/WCFService.svc" binding="basicHttpBinding" 
     bindingConfiguration
="StreamedHTTP"
     contract
="BitAEC5.WCFService.TenderBidService.ITenderTopicList"/>

 

6.自己到目前为止,在开发中还没有用过DataContract和MessageContrace,说明自己对WCF的理解和使用都非常片面,有很大局限性。

7.刚才在MS Downloader里面下载了一些关于WCF的Samples,觉得不错。但自己对高级查询中的一些查询项还是摸不太清头脑,不晓得Product/Technology和Category这两个关键的查询选项到底应该怎么设,只要统统暂设成All。
地址:http://www.microsoft.com/downloads/advancedsearch.aspx?displaylang=en

8.看了一个关于MessageContract的最简单的例子,就是定义一个[MessageContract]的类型,并在其中定义[MessageHeader]和[MessaegBodyMember]。然后这个类型就可以作为一个WCF服务的调用参数类型和返回参数类型了。

下班了,下周继续 ^&^


posted @ 2007-12-07 17:26  EagleFish(邢瑜琨)  阅读(731)  评论(3编辑  收藏  举报