首先复习下WCF:
WCF实际上是构建了一个框架,这个框架实现了在互联系统中各个Application之间如何通信。使得Developers和Architect在构建分布式系统中,无需在考虑如何去实现通信相关的问题,更加关注与系统的业务逻辑本身。而在WCF Infrastructure中,各个Application之间的通信是由Endpoint来实现的。
Endpoint的结构
Endpoint包含以下4个对象:
- Address: Address通过一个URI唯一地标识一个Endpoint,并告诉潜在的WCF service的调用者如何找到这个Endpoint。所以Address解决了Where to locate the WCF Service?
- Binding: Binding实现在Client和Service通信的所有底层细节。比如Client与Service之间传递的Message是如何编码的——text/XML, binary,MTOM;这种Message的传递是采用的哪种Transport——TCP, Http, Named Pipe, MSMQ; 以及采用怎样的机制解决Secure Messaging的问题——SSL,Message Level Security。所以Binding解决的是How to communicate with service?
- Contract: Contract的主要的作用是暴露某个WCF Service所提供的所有有效的Functionality。从Message Exchange的层面上讲,Contract实际上是抱每个Operation转化成为相对应的Message Exchange Pattern——MEP(Request/Response; One-way; Duplex)。所以Contract解决的是What functionalities do the Service provide?
- Behavior: Behavior的主要作用是定制Endpoint在运行时的一些必要的Behavior。比如Service 回调Client的Timeout;Client采用的Credential type;以及是否支持Transaction等。
具体可参考 http://www.cnblogs.com/artech/archive/2007/02/28/659331.html
windows app 就是Client了:To call a WCF service from a Windows Store application, use the Add Service Reference feature of Visual Studio 2012. You will notice a few changes in the functionality of Add Service Reference when done within a Windows Store application. First no configuration file is generated. Windows Store applications do not use configuration files, so they must be configured in code. This configuration code can be found in the References.cs file generated by Add Service Reference. To see this file, make sure to select “Show All Files” in the solution explorer. The file will be located under the Service References and then Reference.svcmap nodes within the project. All operations generated for WCF services within a Windows Store application will be asynchronous using the Task-based asynchronous pattern.
具体可参考http://msdn.microsoft.com/en-us/library/hh556233(v=vs.110).aspx
Serialization V.S. Encoding
Serialization可以看成是把包含相同内容的数据从一种结构 (.NET Object) 转换成另一种结构 (XML) 。要实现在两种不同结构之间的转化,这两种结构之间必须存在一种Mapping。Serialization的是实现由序列化器(Serializer)来负责。而Serializer则利用某种算法(Arithmetic)来提供这种Mapping。我们知道对于一个Managed Type的结构信息——比如它的所有成员的列表,每个成员的Type、访问限制,以及定在每个成员上的属性,作为原数据被存贮在Assembly的原数据表中,这些原数据可以通过反射的机制获得。而XML的结构一般利用XSD来定义。所以 在WCF中的Serialization可以看成是Serializer通过反射的机制分析对象所对应的Type的原数据,从而提供一种算法实现Managed Type的XSD的转化。
我们的.NET Object通过Serialization转化成XML Infoset。但是要使我们的数据能够通过网络协议在网络上传递,必须把生成的XML Infoset转化成字节流(Byte Stream)。所以Encoding关注的是XML Infoset到字节流(Byte Stream)这一段转化的过程。在WCF中,有3中不同的方式可供选择:Binary;Text和MTOM(Message Transmit Optimized Mechanism)。Binary具有最好的Performance,Text具有最好的互操作性,MTOM则有利于大量数据的传送。
可以这样来理解Serialization和Encoding,Sterilization是基于Service Contract的——而实际上它也是定义在Service Contract中,是放在我们的Code中;而Encoding一般由Binding提供,它是和Service无关的,我们一般在Configuration中根据实际的需要选择我们合适的Encoding。
在WCF中,我们有3种不同的Serializer——DataContractSerializer(定义在System.RunTime.Serializtion namespace中)、XMLSerializer(定义在System.XML.Serialization namespace)和NetDataContractSerializer (定义在System.XML.Serialization namespace) 。他们不同的方式实现.NET Object的Serialization。
其中DataContractSerializer为WCF默认的Serializer。
总结出以下的Mapping关系:
1. Root Element为对象的Type Name——DataContractOrder
2. Type的Namespace会被加到XML根节点的Namespace中http://schemas.datacontract.org/2004/07/Artech.WCFSerialization
3. 对象的所有成员以XML Element的形式而不是以XML Attribute的形式输出。
4. 所以对象在XML的输出顺序是按照字母排序。
5. 所有成员的Elelement 名称为成员名称。
6. 不论成员设置怎样的作用域(public,protected,internal,甚至市Private),
所有运用了DataMemberAttribute的成员均被序列化到XML中——private string ProducingArea。
7. Type和成员必须运用DataContractAttribute和DataMemberAttribute才能被序列化。
上面这些都是默认的Mapping关系,在通常情况下我们用默认的这种Mapping往往不能满足我们的需求,为了把.NET序列化成我们需要的XML 结构(比如我们的XmL必须于我们预先定义的XSD一致),我们可以在这两个Attribute(DataContractAttribute和DataMemberAttribute)制定相关的参数来实现。具体做法如下。
1. Root Element可以通过DataContractAttribute中的Name参数定义。
2. Namespace可以通过DataContractAttribute中的NameSpace参数定义。
3. 对象的成员只能以XML Element的形式被序列化。
4. 对象成员对应的XML Element在XML出现的位置可以通过DataMemberAttribute的Order参数来定义。
5. 对象成员对应的Element的名称可以通过DataMemberAttribute中的Name定义。
6. 如果不希望某个成员输出到XML中,可以去掉成员对应的DataMemberAttribute Attribute。
此外DataMemberAttribute还有连个额外的参数:
1. IsRequired:制定该成员为必须的,如果通过工具生成XSD的话,对应的Element的minOccur=“1”
2. EmitDefaultValue:制定是否输入没有赋值的成员(值为默认值)是否出现在XML中。
具体可参考:http://www.cnblogs.com/artech/archive/2007/03/10/669874.html
XMLSerializer
XMLSerializer,这是asmx采用的Serializer。总结出以下的Mapping关系:
- Root Element被指定为类名。
- 不会再Root Element中添加相应的Namaspace。
- 对象成员以XML Element的形式输出。
- 对象成员出现的顺利和在Type定义的顺序一致。
- 只有Public Field和可读可写得Proppery才会被序列化到XML中——比如定义在XMLProduct中的internal string ProducingArea没有出现在XML中。
- Type定义的时候不需要运用任何Attribute。
以上这些都是默认的Mapping关系,同DataContractSerializer一样,我们可以通过在Type以及它的成员中运用一些Attribute来改这种默认的Mapping。
- Root Element名称之后能为类名。
- 可以在Type上运用XMLRoot,通过Namaspace参数在Root Element指定Namespace。
- 可以通过在类成员上运用XMLElement Attribute和XMLAttribute Attribute指定对象成员转化成XMLElement还是XMLAttribute。并且可以通过NameSpace参数定义Namespace。
- 可以在XMLElement或者XMLAttribute Attribute 通过Order参数指定成员在XML出现的位置。
- 可以通过XmlIgnore attribute阻止对象成员被序列化。
-
DataContractSerializer V.S. XMLSerializer
上面我们分别分析了两种不同的Serializer,现在我们来简单总结一下他们的区别:
特性
XMLSerializer
DataContractSerializer
默认Mapping
所有Public Field和可读可写Property
所有DataMember Filed、Property
是否需要Attribute
不需要
DataContract DataMember或者Serializable
成员的默认次序
Type中定义的顺序
字母排序
兼容性
.asmx
Remoting
Deserialzation
调用默认构造函数
不会调用
具体可参考:http://www.cnblogs.com/artech/archive/2007/03/10/670446.html
MSMQ在WCF的运用
在WCF中,MSMQ提供的数据传输功能被封装在一个Binding中,提供WCF Endpoint之间、以及Endpoint和现有的基于MSMQ的Application进行通信的实现。为此WCF为我们提供了两种不同的built-in binding:
- NetMsmqBinding:从提供的功能和使用 方式上看,NetMsmqBinding和一般使用的binding,比如basicHttpBinding,netTcpBinding没有什么区别:在两个Endpoint之间实现了数据的通信,所不同的是,它提供的是基于MSMQ的Reliable Messaging。从变成模式上看,和一般的binding完全一样。
- MsmqIntegrationBinding:从命名上我们可以看出,MsmqIntegrationBinding主要用于需要将我们的WCF Application和现有的基于MSMQ的Application集成的情况。MsmqIntegrationBinding实现了WCF Endpoint和某个Message Queue进行数据的通信,具体来说,就是实现了单一的向某个Message Queue 发送Message,和从某个Message Queue中接收Message的功能。从编程模式上看,也有所不同,比如Operation只接收一个MsmqMessage<T>的参数。
具体可参考:http://www.cnblogs.com/artech/archive/2007/06/29/799529.html
参数的格式:
RequestFormat = WebMessageFormat.Xml,BodyStyle = WebMessageBodyStyle.Bare
这里讲得很详细
http://www.cnblogs.com/artech/archive/2012/02/06/wcf-rest-web-message-body-style.html
后面还应有传输方式的选择,安全和身份验证等。
Calling a WCF service from a Metro application – adding security: http://blogs.msdn.com/b/piyushjo/archive/2011/10/11/calling-a-wcf-service-from-a-metro-application-adding-security.aspx
WCF 64K限制的解决: http://www.asquestion.com/question/2D373033363333353436
<services>
<service name="Service.IService">
<clear />
<endpoint binding="basicHttpBinding" contract="Service.IService" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647"
maxArrayLength="16348" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
</basicHttpBinding>
<webHttpBinding>
<binding maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" />
</webHttpBinding>
</bindings>