一步一個腳印學習WCF系列之WCF契約設計—3-復雜類型序列化之數據契約DataContractAttribute


  閱讀目錄

  一:DataContractAttribute 

  二:DataMemberAttribute

  三:實例

  一:DataContractAttribute

    . 在schema和CRL類型之間轉換

      在WCF當中我們推薦的一種序列化方式是使用數據契約的這種方式,使用數據契約的方式和一般的序列化的方式是種類似的方式,也是在我們需要進行序列化的數據上面加DataContract特性,在加完DataContract特性以后,.NET本身會為我們實現schema也就是XSD和CRL類型之間的轉換

    . 總是要提供命名空間

    . 能夠提供顯式的Name

      我們希望對Book這個類所表示的對象來進行序列化的話,我們可以在它上面加上DataContract特性,並且指明說在SOAP消息當中以什么名字來傳遞它,在這里是SOAP消息當中我們以BookInfo名稱來傳遞它

1 [DataContract(Name="BookInfo",Namespace="http://schemas.menglin.net")]
2 public class Book
3 {
4 }

   二:DataMemberAttribute

    如果我們使用數據契約來描述的類,只有我們顯式的把這個類當中的具體的成員通過DataMember來標記了,才表明這個成員是要參與到序列化當中,如果某一個成員沒有使用DataMember來標記,表明這個成員不需要參與到序列化當中

    . 應用於域和屬性

      -應用於域

               我們希望_name這個數據參與到序列化當中,或者說把它添加到SOAP數據包中,我們可以用DataMember特性來標記這個私有字段,且通過Name特性來明確_name在SOAP數據包中是使用什么名稱的,也就是它使用什么具體名稱存放於SOAP當中

1 [DataMember(Name = "BookName", IsRequired = false, Order = 0)]
2 private string _name;

      -應用於屬性

        我們希望Name這個數據參與到序列化當中,或者說把它添加到SOAP數據包中,我們可以用DataMember特性來標記這個屬性,且通過Name特性來明確Name在SOAP數據包中是使用什么名稱的,也就是它使用什么具體名稱存放於SOAP當中

 1 private string _name;
 2 /// <summary>
 3 /// 書本名稱
 4 /// </summary>
 5 [DataMember(Name="BookName", IsRequired = false,Order = 0)]
 6 public string Name
 7 {
 8     get { return _name; }
 9     set { _name = value; }
10 }

    . 可以指定排列順序

      我們要進行序列化的對象它在SOAP數據包中進行排序的位置,也就是它排在第幾號,在這里Name在序列化的時候在SOAP數據包中排在第一位,如果我們沒有指定Order的話,默認按字母排序

 1 private string _name;
 2 /// <summary>
 3 /// 書本名稱
 4 /// </summary>
 5 [DataMember(Name="BookName", IsRequired = true,Order = 0)]
 6 public string Name
 7 {
 8       get { return _name; }
 9       set { _name = value; }
10 }

     . 能夠顯式的指定Name和IsRequired

      -Name

        通過Name特性來明確_name在SOAP數據包中是使用什么名稱的,也就是它使用什么具體名稱存放於SOAP當中

      -IsRequired

        這個屬性Name是不是可為空的,也就是說在序列化之前是否必須要被賦值,IsRequired=true,表示Name在序列化之前必須要被賦值

 1 private string _name;
 2 /// <summary>
 3 /// 書本名稱
 4 /// </summary>
 5 [DataMember(Name="BookName", IsRequired = true,Order = 0)]
 6 public string Name
 7 {
 8       get { return _name; }
 9       set { _name = value; }
10 }

   三:實例

    使用數據契約進行描述時,在WCF當中我們推薦的方式是對屬性進行DataMember的描述,而不是通過字段進行描述,主要體現在OO的設計風格,對於類當中的成員,我們需要屏蔽掉外部的訪問,也就是對於外部的對象而言,它只能訪問這個類當中的屬性,而不是直接去訪問這個類當中的字段

    我們定義了一個Book類,並且指定了它的名稱“Book_DataContract”,然后我們對這個類當中的屬性進行了DataMember的描述,指明了它的名稱,和在序列化之前是否要賦值的,以及在序列化的時候所排序的位置

    1:Book.cs 數據契約的定義

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Runtime.Serialization;
 6 
 7 namespace DataContract.Service
 8 {
 9     [DataContract(Name = "Book_DataContract", Namespace = "http://schames.menglin.net/2012/05/08")]
10     public class Book
11     {
12         private int _id;
13         /// <summary>
14         /// 書本ID
15         /// </summary>
16         [DataMember(Name = "ID_DataMember", IsRequired = false, Order = 0)]
17         public int ID
18         {
19             get { return _id; }
20             set { _id = value; }
21         }
22 
23         private string _name;
24         /// <summary>
25         /// 書本名稱
26         /// </summary>
27         [DataMember(Name = "Name_DataMember", IsRequired = false, Order = 1)]
28         public string Name
29         {
30             get { return _name; }
31             set { _name = value; }
32         }
33         private string _author;
34         /// <summary>
35         /// 作者
36         /// </summary>
37         [DataMember(Name = "Author_DataMember", IsRequired = false, Order = 2)]
38         public string Author
39         {
40             get { return _author; }
41             set { _author = value; }
42         }
43       
44         private string _publisher;
45         /// <summary>
46         /// 出版商
47         /// </summary>
48         [DataMember(Name = "Publisher_DataMember", IsRequired = false, Order = 3)]
49         public string Publisher
50         {
51             get { return _publisher; }
52             set { _publisher = value; }
53         }
54 
55         private string _unit;
56         /// <summary>
57         /// 單位
58         /// </summary>
59         [DataMember(Name = "Unit_DataMember", IsRequired = false, Order = 4)]
60         public string Unit
61         {
62             get { return _unit; }
63             set { _unit = value; }
64         }
65 
66         private string _price;
67         /// <summary>
68         /// 價格
69         /// </summary>
70         [DataMember(Name = "Price_DataMember", IsRequired = false, Order = 5)]
71         public string Price
72         {
73             get { return _price; }
74             set { _price = value; }
75         }
76 
77         private string _addtime;
78         /// <summary>
79         /// 入庫時間
80         /// </summary>
81         [DataMember(Name = "AddtTime_DataMember", IsRequired = false, Order = 6)]
82         public string AddtTime
83         {
84             get { return _addtime; }
85             set { _addtime = value; }
86         }
87     }
88 }

    2:IBookService.cs 服務契約的定義

      IBookService使用了Book,IBookService.cs是我們在Host或者在Server這一端為客戶端所提供的服務,在這個服務里面我們主要為客戶端提供了一個叫作“GetMyBook()”,一個叫作“SaveMyBook()”這么兩個方法,這兩個方法使用了Book對象,對於這個類而言的話,我們使用了IBookService這個接口來進行描述,同樣我們指定了服務契約的名稱和這個服務契約里面具體操作的名稱

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.ServiceModel;
 6 
 7 using DataContract.Model;
 8 
 9 namespace DataContract.Service
10 {
11     [ServiceContract(Name = "Book_ServiceContract", Namespace = "http://schames.menglin.net/2012/05/08")]
12     public interface IBookService
13     {
14         [OperationContract(Name = "GetBook", Action = "http://schames.menglin.net/2012/05/08")]
15         Book GetMyBook();
16 
17         [OperationContract(Name = "SaveBook", Action = "http://schames.menglin.net/2012/05/09")]
18         void SaveMyBook(Book book);
19     }
20 
21     public class BookService : IBookService
22     {
23         private Book _book;
24         public Book GetMyBook()
25         {
26             return _book;
27         }
28 
29         public void SaveMyBook(Book book)
30         {
31             _book = book;
32         }
33     }
34 }

    3:Program.cs 服務宿主

      在Host這一端就是把BookService這個服務加載到Host當中

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.ServiceModel;
 6 
 7 using DataContract.Service;
 8 
 9 namespace Host
10 {
11     class Program
12     {
13         static void Main(string[] args)
14         {
15             using (ServiceHost host = new ServiceHost(typeof(BookService)))
16             {
17                 host.Open();
18                 Console.ReadLine();
19             }
20         }
21     }
22 }

     4:App.config 服務的配置

      IMetadataExchange這個接口的作用是用於對外提供服務的元數據,所謂元數據,大家可以理解為”描述數據的數據“,什么叫作“描述數據的數據”,比如:我們現在希望Host對外提供BookService這個服務,這個服務里面包含了若干個方法,以及這些方法有一些參數,這些方法的名稱,這些參數的名稱,以及Book里面具體的屬性都是什么,以及它具體的類型,以及它排序的方式,我們把這些數據稱為元數據,我們添加IMetadataExchange這個接口就是為了對外暴露元數據,我們為什么要對外暴露元數據呢?主要原因在於對於客戶端而言它為了能夠訪問服務器端的服務的話,它必須要獲得這些元數據,也就是它必須要獲得服務器這一端服務的名稱,方法的名稱,以及具體數據的定義,這些定義如何來獲得呢?就是通過IMetadataExchange這種方式來獲得這些數據,因此在這里我們需要對外暴露出IMetadata這種交換的信息,使得客戶端和服務器端之間能夠互通

1 <endpoint address="mex"
2           binding="mexHttpBinding"
3           contract="IMetadataExchange"  />

 

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <configuration>
 3     <system.serviceModel>
 4         <behaviors>
 5             <serviceBehaviors>
 6                 <behavior name="serviceBehavior">
 7                     <serviceMetadata httpGetEnabled="true" />
 8                 </behavior>
 9             </serviceBehaviors>
10         </behaviors>
11         <services>
12             <service name="DataContract.Service.BookService" behaviorConfiguration="serviceBehavior">
13                 <endpoint address="BookService"
14                           binding="netTcpBinding"
15                           contract="DataContract.Service.IBookService" />
16                 <endpoint address="mex"
17                           binding="mexHttpBinding"
18                           contract="IMetadataExchange"  />
19                 <host>
20                     <baseAddresses>
21                         <add baseAddress="http://localhost:8000"/>
22                         <add baseAddress="net.tcp://localhost:9000"/>
23                     </baseAddresses>
24                 </host>
25             </service>
26         </services>
27     </system.serviceModel>
28 </configuration>

  5:Form1.cs 客戶端

    在這個實例中提供了一個Winform,在這個Winform里面有兩個Button,一個叫做“得到書”,一個叫做“保存書”

   

  啟動Host

  

  打開服務

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM