wp8使用Beetle.NetPackage實現基於TCP通訊的訂單查詢

smark發表於2013-09-23

在新版本的Beetle.NetPackage中提供了對Protobuf和Controller的支援,所以在WP8下使用Beetle.NetPackage進行基於TCP的資料互動則一件非常簡單事情.下面通過元件在WP8下簡單實現基於TCP通訊的訂單線上查詢功能.

協議定義

為了簡化互動資料的處理在這裡使用Protobuf來描述資料互動,通過Protobuf制訂一系列的請求和應答物件來代替平常在TCP下繁瑣的資料流處理過程.下面通過Protobuf來描述訂單查詢的通訊協議.

  1 [ProtoContract]
  2     public class GetCustomer
  3     {
  4         [ProtoMember(1)]
  5         public string Name { get; set; }
  6     }
  7 
  8     [ProtoContract]
  9     public class GetCustomerResponse
 10     {
 11 
 12         [ProtoMember(1)]
 13         public IList<Customer> Items
 14         {
 15             get;
 16             set;
 17         }
 18 
 19     }
 20 
 21     [ProtoContract]
 22     public class Customer
 23     {
 24         [ProtoMember(1)]
 25         public string ID
 26         {
 27             get;
 28             set;
 29         }
 30         [ProtoMember(2)]
 31         public string Name
 32         {
 33             get;
 34             set;
 35         }
 36         public override string ToString()
 37         {
 38             return Name;
 39         }
 40     }
 41 
 42     [ProtoContract]
 43     public class GetEmployee
 44     {
 45         [ProtoMember(1)]
 46         public string Name { get; set; }
 47     }
 48 
 49     [ProtoContract]
 50     public class GetEmployeeResponse
 51     {
 52         [ProtoMember(1)]
 53         public IList<Employee> Items
 54         {
 55             get;
 56             set;
 57         }
 58     }
 59 
 60     [ProtoContract]
 61     public class Employee
 62     {
 63 
 64         [ProtoMember(1)]
 65         public string ID
 66         {
 67             get;
 68             set;
 69         }
 70         [ProtoMember(2)]
 71         public string Name
 72         {
 73             get;
 74             set;
 75         }
 76         public override string ToString()
 77         {
 78             return Name;
 79         }
 80         
 81     }
 82 
 83     [ProtoContract]
 84     public class OrderSearch
 85     {
 86         [ProtoMember(1)]
 87         public string Employee { get; set; }
 88         [ProtoMember(2)]
 89         public int PageIndex { get; set; }
 90         [ProtoMember(3)]
 91         public string Customer { get; set; }
 92         [ProtoMember(4)]
 93         public string FromDate { get; set; }
 94         [ProtoMember(5)]
 95         public string ToDate { get; set; }
 96     }
 97 
 98     [ProtoContract]
 99     public class OrderSearchResponse
100     {
101         [ProtoMember(1)]
102         public IList<Order> Items
103         {
104             get;
105             set;
106         }
107         [ProtoMember(2)]
108         public int PageIndex
109         {
110             get;
111             set;
112         }
113         [ProtoMember(3)]
114         public int Pages
115         {
116             get;
117             set;
118         }
119     }
120 
121     [ProtoContract]
122     public class Order
123     {
124         [ProtoMember(1)]
125         public string OrderID { get; set; }
126         [ProtoMember(2)]
127         public string Employee { get; set; }
128         [ProtoMember(3)]
129         public string Customer { get; set; }
130         [ProtoMember(4)]
131         public string OrderDate { get; set; }
132         [ProtoMember(5)]
133         public string RequiredDate { get; set; }
134         [ProtoMember(6)]
135         public string ShippedDate { get; set; }
136         [ProtoMember(7)]
137         public string ShipName { get; set; }
138         [ProtoMember(8)]
139         public string ShipAddress { get; set; }
140         [ProtoMember(9)]
141         public string ShipCity { get; set; }
142         [ProtoMember(10)]
143         public string ShipRegion { get; set; }
144     }
145 
146     [ProtoContract]
147     public class GetOrderDetail
148     {
149         [ProtoMember(1)]
150         public string OrderID { get; set; }
151     }
152 
153     [ProtoContract]
154     public class GetOrderDetailResponse
155     {
156         [ProtoMember(1)]
157         public IList<OrderDetail> Items
158         {
159             get;
160             set;
161         }
162     }
163 
164     [ProtoContract]
165     public class OrderDetail
166     {
167         [ProtoMember(1)]
168         public string OrderID { get; set; }
169         [ProtoMember(2)]
170         public string Product { get; set; }
171         [ProtoMember(3)]
172         public double UnitPrice { get; set; }
173         [ProtoMember(4)]
174         public int Quantity { get; set; }
175         [ProtoMember(5)]
176         public float Discount { get; set; }
177     }
View Code

由於這裡使用了protobuf-net,所以通過類和特性來結合,其實規範方便其他平臺處理還是建議使用proto檔案描述來生成對應的類,這樣可以方便生成C++,JAVA等不同平臺的互動物件.

定義TCP通訊物件

通過Beetle.NetPackage對protobuf的支援,在WP8下建立相應的TCP通訊是件非常簡單的事情.

1 Beetle.NetPackage.ProtoPakcage.Register(typeof(MainPage).Assembly);
2             if (mClient == null)
3             {
4                 mClient = new Beetle.NetPackage.NetClient("192.168.0.104", 9088, new Beetle.NetPackage.ProtoPakcage(), this);
5                 mClient.LittleEndian = false;
6             }
7             mClient.Connect();

在使用protobuf前通過ProtoPakcage.Register把程式集下面對應的protobuf訊息註冊到元件中,然後建立相應的NetClient就可以進行資料通訊.在這裡為了和android互動相容把client的LittleEndian屬性設定成false即在處理資料過程採用高字序作為一些資料型別的處理方式.

訊息路由分發

在新版本的Beetle.NetPackage中提供簡單的訊息路由功能,因此在編寫訊息接收處理的時候再也不需要通過if來判斷不同訊息去呼叫方法.使用訊息路由並不需開發人員定義複雜的訊息規則,只需要定義相應訊息型別的引數即可讓元件幫助完成這個事情.

 1 public void OnSearchOrderResponse(Beetle.NetPackage.NetClient client, OrderSearchResponse e)
 2         {
 3             if (e.Items == null)
 4                 lstOrders.ItemsSource = null;
 5             else
 6                 lstOrders.ItemsSource = e.Items.ToList();
 7             mPageIndex = e.PageIndex;
 8             mPages = e.Pages;
 9         }
10 
11         public void OnGetEmployee(Beetle.NetPackage.NetClient client, GetEmployeeResponse e)
12         {
13             mEmployees = e.Items;
14             lstEmployee.ItemsSource = e.Items.ToList();
15         }
16         public void OnGetCustomer(Beetle.NetPackage.NetClient client, GetCustomerResponse e)
17         {
18             mCustomers = e.Items;
19             lstCustomer.ItemsSource = e.Items.ToList();
20 
21         }
22         public void OnGetOrderDetail(Beetle.NetPackage.NetClient client, GetOrderDetailResponse e)
23         {
24             DialogOrderDetail detail = new DialogOrderDetail();
25             CustomMessageBox mOrderDetailDialog = new CustomMessageBox
26             {
27                 Content = detail,
28                 Title = "OrderDetail",
29                 RightButtonContent = "OK"
30             };
31             detail.ListSelector.ItemsSource = e.Items.ToList();
32             mOrderDetailDialog.Show();
33         }

以上是制定不同訊息的處理過程,在接收訊息的時候觸發這些過程只需要簡單地呼叫Controller.Invoke方法即可完成.

1 public void ClientReceive(Beetle.NetPackage.NetClient client, object message)
2         {
3             this.Dispatcher.BeginInvoke(() =>
4             {
5                 Beetle.NetPackage.Controller.Invoke(this, mClient, message);
6             });
7         }

在訊息接收方法中呼叫Controller.Invoke元件會自動匹配相應訊息處理的方法並呼叫,由於是元件自動匹配所以在制定方法的過程也需要遵循一個規則,就是在一個物件中對應訊息處理的方法必須是唯一的. 

執行效果

  

總結

通過Beetle.NetPackage只需要很少量的程式碼就能完成基於TCP的物件資料互動處理,而開發者是完全不用關心下層的協議處理細節,Beetle.NetPackage不僅僅提供對wp8的支援,還提供對flash和android的支援.

下載sample 

 元件開源官網:https://beetlenp.codeplex.com/

相關文章