如果你在使用WCF暴露服务而且使用svcutil.exe来为创建访问服务代码,一般情况下你不需要关心在客户端和服务端间传输的消息的线上表 示。数据契约知道WCF把一个.NET类型序列化成一个XML信息集和讲一个XML信息集反序列化成一个.NET类型。XML信息集可能在线上以文件或者 二进制形式编码,这些取决于通信过程中所使用的绑定,但是再次,.NET代码不会意识到编码的存在。这种方式就好比你在代码中使用.NET类型但是一个基 于标准的XML信息集的编码表示在线上具体传输。
然而有很多种情况你需要在客户端和服务端使用不同的类型。如果客户端和服务端 是不同组织开发的那么这很有可能,或者仅仅单边的通信是使用WCF。事实上,如果你不适用svcutil.exe或者添加服务引用来生成客户端代理,将会 有很大的客户端成员名字与服务端成员名字不同的情况发生的可能。但是通过使用[DataMember]属性来控制这些名字,你可以让它们在XML表示中是 相同的。只要客户端和服务端使用一个等效XML表示,对WCF来说,把XML信息反序列化成不同的.NET类型是可以的。如果两个类序列化成同样的XML 元数据,数据契约表示的这些类可以被认为是一致的。对数据契约来说,要保持一致,它们必须有相同的命名空间,名字和成员。XML中的数据成员必须是同样的 名字并且出现在同样的位置。简要的说,它们在线上必须是不可区分的。
列表2.26 显示了两个等效的数据契约。第一个契约由服务端暴露;第二个类由客户端描述。这两个契约是等效的而且生成了唯一的XML元数据定义。在服务端,默认情况 下,WCF将会对XML元素按照字母顺序排列,所以第二个元数据将会强制数据元素按照字母顺序排列。因为名字为”StockPriceSvc”和名字 为”Currency”的属性各自独立的存在于DataContract和DataMember中,XSD在第二个契约中生存的契约与第一个相同。
列表2.26 等效数据契约
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace EssentialWCF
{
[DataContract(Namespace="http://EssentialWCF")]
public class StockPriceSvc //V1
{
[DataMember] public double CurrentPrice;
[DataMember] public DateTime CurrentTime;
[DataMember] public string Ticker;
[DataMember] public string Currency;
}
[DataContract(Namespace = "http://EssentialWCF",Name = "StockPriceSvc")]
public class StockPrice //V2
{
[DataMember(Order = 2)]
public double CurrentPrice;
[DataMember(Order = 3)]
public DateTime CurrentTime;
[DataMember(Order = 4)]
public string Ticker;
[DataMember(Order = 1, Name = "Currency")]
public string Money;
}
}
使用集合
集合是.NET中非常方便的数据结构,它集中了动态内存分配,枚举和列表指向的优势。 尽管很有用,但是没有XSD或WCF的标准与一个集合等效。因此,讲一个集合序列化为XML,WCF需要将集合按照数组对待。事实上,一个集合的线上级别 序列化与一个数组是一致的。另外对集合(类型继承于ICollection<T>)来说,这也是相同的,因为它的类型继承自 IEnumerable<T>或者IList<T>.
列表2.27显示了一个使用集合的数据契约和 操作。这个集合使用[CollectionDataContract]属性来修饰,它是特别用来提供这个目的的WCF的特别属性。这个属性指导WCF把任 何支持IEnumerable接口并且实现了一个数组的Add方法的类型序列化成XML。StockPriceCollection类继承自List 类,List类继承于ICollection基类接口来实现序列化。
列表2.27 从一个服务端暴露一个集合
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ServiceModel;
namespace EssentialWCF
{
[DataContract(Namespace = "http://EssentialWCF")]
public class StockPrice
{
[DataMember] public double CurrentPrice;
[DataMember] public DateTime CurrentTime;
[DataMember] public string Ticker;
}
[CollectionDataContract]
public class StockPriceCollection : List<StockPrice>
{
}
[ServiceContract]
public class StockService
{
[OperationContract]
private StockPriceCollection GetPriceAsCollection(string[] tickers)
{
StockPriceCollection list = new StockPriceCollection();
for (int i = 0; i < tickers.GetUpperBound(0) + 1; i++)
{
StockPrice p = new StockPrice();
p.Ticker = tickers[i];
p.CurrentPrice = 94.85;
p.CurrentTime = DateTime.Now;
list.Add(p);
}
return list;
}
}
}
===========
转载自