在本篇文章上一部分
Order Processing
的例子中,我们看到原本已
Collection
形式定义的
DetailList
属性(
public IList<TDetail> DetailList
),在
Data Contract
中却以
Array
的方式体现(
public OrderDetail[] DetailList
)。我们现在就来详细地讨论一下基于
Collection & Dictionary
的
Data Contract
。
Data Contract for Collection
我们照例用例子来说明问题,在这里我们创建一个批量处理Order的Service,于是我们创建了一个OrderCollection Type:
namespace Artech.SpecialDataContract.Contract
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[DataContract]
public class Order
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[DataMember]
public Guid OrderID
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
get;
set; }
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[DataMember]
public DateTime OrderDate
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
get;
set; }
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
public class OrderCollection : List<Order>
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
}
下面是Service Contract的定义:
namespace Artech.SpecialDataContract.Contract
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[ServiceContract]
public interface IOrderManager
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[OperationContract(Name = "ProcessWithCollection")]
void Process(OrderCollection orders);
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
面是OrderCollection 在XSD中的呈现:
<?
xml version="1.0" encoding="utf-8"
?>
<
xs:schema
elementFormDefault
="qualified"
targetNamespace
="http://schemas.datacontract.org/2004/07/Artech.SpecialDataContract.Contract"
xmlns:xs
="http://www.w3.org/2001/XMLSchema"
xmlns:tns
="http://schemas.datacontract.org/2004/07/Artech.SpecialDataContract.Contract"
xmlns:ser
="http://schemas.microsoft.com/2003/10/Serialization/"
>
<
xs:import
schemaLocation
="http://artech/Artech.SpecialDataContract/OrderManagerService.svc?xsd=xsd1"
namespace
="http://schemas.microsoft.com/2003/10/Serialization/"
/>
<
xs:complexType
name
="ArrayOfOrder"
>
<
xs:sequence
>
<
xs:element
minOccurs
="0"
maxOccurs
="unbounded"
name
="Order"
nillable
="true"
type
="tns:Order"
/>
</
xs:sequence
>
</
xs:complexType
>
<
xs:element
name
="ArrayOfOrder"
nillable
="true"
type
="tns:ArrayOfOrder"
/>
<
xs:complexType
name
="Order"
>
<
xs:sequence
>
<
xs:element
minOccurs
="0"
name
="OrderDate"
type
="xs:dateTime"
/>
<
xs:element
minOccurs
="0"
name
="OrderID"
type
="ser:guid"
/>
</
xs:sequence
>
</
xs:complexType
>
<
xs:element
name
="Order"
nillable
="true"
type
="tns:Order"
/>
</
xs:schema
>
加上通过Add Service Reference默认生成的Class,我们可以很清楚地看出Collection是以Array的形式呈现的(Artech.SpecialDataContract.Client.OrderManagerService.Order[] orders):
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="OrderManagerService.IOrderManager")]
public
interface IOrderManager
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOrderManager/ProcessWithCollection", ReplyAction="http://tempuri.org/IOrderManager/ProcessWithCollectionResponse")]
void ProcessWithCollection(Artech.SpecialDataContract.Client.OrderManagerService.Order[] orders);
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
}
因为Array相对很Common的数据类型,基本上所有的厂商均提供了对Array的支持,这也是WCF在通过Add Service Reference生成Client端代码的时候,会生成Array的原因。不过并不是我们只有唯一的选择,事实上VS为此提供了扩展,允许我们对于基于Collection 的Data Contract生成我们需要的各种类型,我们只需要在Add Service Reference的时候选择“Configure Service Reference”进行相应的配置:
通过上面的截图,我们发现在Collection Type一项我们有若干选项,我们可以选择我们希望生成的数据类型:Array,ArrayList,LinkedList,Generic List,Collection和BindingList。
Data Contract for Dictionary
前面的内容,我们分别讨论了基于Generic和Collection的Data Contract,接下来,我们来讨论最后一个特殊的数据类型的Data Contract:Dictionary。
延续上面的Order Batch Processing的例子,不过我们现在处理的不是一个OrderCollection对象,而是一个Dictionary对象,线面是Service Contract和Order的定义:
namespace Artech.SpecialDataContract.Contract
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[ServiceContract]
public interface IOrderManager
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[OperationContract(Name = "ProcessWithCollection")]
void Process(OrderCollection orders);
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[OperationContract(Name = "ProcessWithDictionary")]
void Process(IDictionary<Guid, Order> orders);
![](https://i-blog.csdnimg.cn/blog_migrate/eec4c0236afc26744c9c4e910bc34958.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
}
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
[DataContract]
public
class Order
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[DataMember]
public Guid OrderID
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
get;
set; }
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[DataMember]
public DateTime OrderDate
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
get;
set; }
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
}
闲话少说,我们来看XSD:
Data Contract的名称为ArrayOfKeyValueOfguidOrder_SkVQi6O3=ArrayOfKeyValueOf+guid(Key的类型)+Order(Value)+_SkVQi6O3(Hash Value)。从该XSD的结构我们不难看出,只是一个数组,每个元素为Key-Value pair。
我们照例看看通过Add Service Reference方式生成的Client端code中的对应的定义:
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="OrderManagerService.IOrderManager")]
public
interface IOrderManager
{
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IOrderManager/ProcessWithDictionary", ReplyAction="http://tempuri.org/IOrderManager/ProcessWithDictionaryResponse")]
void ProcessWithDictionary(System.Collections.Generic.Dictionary<System.Guid, Artech.SpecialDataContract.Client.OrderManagerService.Order> orders);
![](https://i-blog.csdnimg.cn/blog_migrate/4fd96b3cf02f4c7b5c8964ac8167f7af.gif)
}
生成的是一个System.Collections.Generic.Dictionary类型。同Collection一样,也依然可以有多种选择:
![](https://i-blog.csdnimg.cn/blog_migrate/ed8f5c2db6eeeb9adfd39bc99292cbfe.jpeg)