[原创]谈谈WCF中的Data Contract(2):WCF Data Contract对Generic的支持

通过第一部分的介绍,我们可以体会到,WCF 的Data Contract在CLR Type和Neutral Contract之间搭建了一座桥梁,弥合了.NET世界和厂商中立世界的差异。通过WCF Data Contract我们将CLR Data Type暴露成一个厂商中立的数据结构的描述,同样通过WCF Data Contract我们将一个现有的CLR Data Type和既定的Neutral contract进行适配。

在.NET中,基于Primary Type,比如Int32,String等等,他们具有一个简单的默认的序列化方式和结构,可以说他们不需要Data Contract。接下来我们主要讨论的是一些相对比较特殊的、完全基于.NET的Data Type,比如Generic、Collection,和Dictionary。首先,我们结合例子来谈谈基于Generic的Data Type的Data Contract。

假设我们需要创建一个用于处理一些单据(Bill)的Service,比如如Order Bill、Sales Bill等。一般的单据都有一个单据头(Header)和明细(Detail)列表,为此我们创建了一个Generic的Bill。并

namespaceArtech.SpecialDataContract.Contract
{
[DataContract]
publicclassBill<THeader,TDetail>
{
[DataMember]
publicTHeaderHeader
{get;set;}

[DataMember]
publicIList<TDetail>DetailList
{get;set;}
}


[DataContract]
publicclassOrderHeader
{
[DataMember]
publicGuidOrderID
{get;set;}

[DataMember]
publicDateTimeOrderDate
{get;set;}
}


[DataContract]
publicclassOrderDetail
{
[DataMember]
publicGuidProductID
{get;set;}

[DataMember]
publicintQuantity
{get;set;}
}


}

为处理订单单据创建了机遇订单的Header和Detail。

对于一个Neutral Service Contract和Neutral Data Contract本身是不可能支持Generic的,也就是Neutral Contract只能是对一个具体的CLR Type的体现。所以在定义Service Contract的时候,对于那些包含Generic Type作为参数或者返回值得Operation,我们必须指定一个具体的Data Type。所以我们创建了如下一个IBillManager Service Contract:

namespaceArtech.SpecialDataContract.Contract
{
[ServiceContract]
publicinterfaceIBillManager
{
[OperationContract]
voidProcss(Bill<OrderHeader,OrderDetail>orderBill);
}

}

如何我们现在

Host基于这样一个Contract的Service,你猜我们作为参数的数据类型将会如何体现的。

通过WSDL,我们会发现该Service的Data Contract将会以下面一段XSD的方式来呈现:

<?xmlversion="1.0"encoding="utf-8"?>
<xs:schemaelementFormDefault="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:importschemaLocation="http://artech/Artech.SpecialDataContract/BillManagerService.svc?xsd=xsd1"
namespace
="http://schemas.microsoft.com/2003/10/Serialization/"/>
<xs:complexTypename="BillOfOrderHeaderOrderDetailLZ9Dq20o">
<xs:annotation>
<xs:appinfo>
<GenericTypeName="BillOf{0}{1}{#}"Namespace="http://schemas.datacontract.org/2004/07/Artech.SpecialDataContract.Contract"
xmlns
="http://schemas.microsoft.com/2003/10/Serialization/">
<GenericParameterName="OrderHeader"Namespace="http://schemas.datacontract.org/2004/07/Artech.SpecialDataContract.Contract"/>
<GenericParameterName="OrderDetail"Namespace="http://schemas.datacontract.org/2004/07/Artech.SpecialDataContract.Contract"/>
</GenericType>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
<xs:elementminOccurs="0"name="DetailList"nillable="true"type="tns:ArrayOfOrderDetail"/>
<xs:elementminOccurs="0"name="Header"nillable="true"type="tns:OrderHeader"/>
</xs:sequence>
</xs:complexType>
<xs:elementname="BillOfOrderHeaderOrderDetailLZ9Dq20o"nillable="true"type="tns:BillOfOrderHeaderOrderDetailLZ9Dq20o"/>
<xs:complexTypename="ArrayOfOrderDetail">
<xs:sequence>
<xs:elementminOccurs="0"maxOccurs="unbounded"name="OrderDetail"nillable="true"type="tns:OrderDetail"/>
</xs:sequence>
</xs:complexType>
<xs:elementname="ArrayOfOrderDetail"nillable="true"type="tns:ArrayOfOrderDetail"/>
<xs:complexTypename="OrderDetail">
<xs:sequence>
<xs:elementminOccurs="0"name="ProductID"type="ser:guid"/>
<xs:elementminOccurs="0"name="Quantity"type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:elementname="OrderDetail"nillable="true"type="tns:OrderDetail"/>
<xs:complexTypename="OrderHeader">
<xs:sequence>
<xs:elementminOccurs="0"name="OrderDate"type="xs:dateTime"/>
<xs:elementminOccurs="0"name="OrderID"type="ser:guid"/>
</xs:sequence>
</xs:complexType>
<xs:elementname="OrderHeader"nillable="true"type="tns:OrderHeader"/>
</xs:schema>

对于不习惯看XSD的朋友,我们可以通过Add Service Reference的方式创建本地的Proxy file,借助生成的与之对应的Class来看看这个XSD最终呈现的结构:

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute(
"System.Runtime.Serialization","3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name
="BillOfOrderHeaderOrderDetailLZ9Dq20o",Namespace="http://schemas.datacontract.org/2004/07/Artech.SpecialDataContract.Contract")]
[System.SerializableAttribute()]
publicpartialclassBillOfOrderHeaderOrderDetailLZ9Dq20o:object,System.Runtime.Serialization.IExtensibleDataObject,System.ComponentModel.INotifyPropertyChanged{

[System.NonSerializedAttribute()]
privateSystem.Runtime.Serialization.ExtensionDataObjectextensionDataField;

[System.Runtime.Serialization.OptionalFieldAttribute()]
privateArtech.SpecialDataContract.Client.BillManagerService.OrderDetail[]DetailListField;

[System.Runtime.Serialization.OptionalFieldAttribute()]
privateArtech.SpecialDataContract.Client.BillManagerService.OrderHeaderHeaderField;

[global::System.ComponentModel.BrowsableAttribute(
false)]
publicSystem.Runtime.Serialization.ExtensionDataObjectExtensionData{
get{
returnthis.extensionDataField;
}

set{
this.extensionDataField=value;
}

}


[System.Runtime.Serialization.DataMemberAttribute()]
publicArtech.SpecialDataContract.Client.BillManagerService.OrderDetail[]DetailList{
get{
returnthis.DetailListField;
}

set{
if((object.ReferenceEquals(this.DetailListField,value)!=true)){
this.DetailListField=value;
this.RaisePropertyChanged("DetailList");
}

}

}


[System.Runtime.Serialization.DataMemberAttribute()]
publicArtech.SpecialDataContract.Client.BillManagerService.OrderHeaderHeader{
get{
returnthis.HeaderField;
}

set{
if((object.ReferenceEquals(this.HeaderField,value)!=true)){
this.HeaderField=value;
this.RaisePropertyChanged("Header");
}

}

}


publiceventSystem.ComponentModel.PropertyChangedEventHandlerPropertyChanged;

protectedvoidRaisePropertyChanged(stringpropertyName){
System.ComponentModel.PropertyChangedEventHandlerpropertyChanged
=this.PropertyChanged;
if((propertyChanged!=null)){
propertyChanged(
this,newSystem.ComponentModel.PropertyChangedEventArgs(propertyName));
}

}

}


[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute(
"System.Runtime.Serialization","3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name
="OrderHeader",Namespace="http://schemas.datacontract.org/2004/07/Artech.SpecialDataContract.Contract")]
[System.SerializableAttribute()]
publicpartialclassOrderHeader:object,System.Runtime.Serialization.IExtensibleDataObject,System.ComponentModel.INotifyPropertyChanged{

[System.NonSerializedAttribute()]
privateSystem.Runtime.Serialization.ExtensionDataObjectextensionDataField;

[System.Runtime.Serialization.OptionalFieldAttribute()]
privateSystem.DateTimeOrderDateField;

[System.Runtime.Serialization.OptionalFieldAttribute()]
privateSystem.GuidOrderIDField;

[global::System.ComponentModel.BrowsableAttribute(
false)]
publicSystem.Runtime.Serialization.ExtensionDataObjectExtensionData{
get{
returnthis.extensionDataField;
}

set{
this.extensionDataField=value;
}

}


[System.Runtime.Serialization.DataMemberAttribute()]
publicSystem.DateTimeOrderDate{
get
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值