[Xamarin]Visual Studio中使用PCL專案加入WCF WebService參考

[Xamarin]Visual Studio中使用PCL專案加入WCF WebService參考

APP在應用時經常會用到WebService服務,在Xamarin中若同時要讓iOS與Android叫用WebService時,
除了分別在iOS與Android中叫用WebService外,
還可以使用PCL專案(portable library class,中文叫可攜式類別庫),
並使用VisualStudio中的加入服務參考的方式快速度建立出WebService服務。

 

假設我們現有一個WCF Service服務,小小修改了一下預設提供的方法如下程式碼:

        {
            return string.Format("WebService說:你輸入的數值為: {0}", value);
        }

 

然後我們分別建立Android、iOS以及PCL三個專案,並讓Android與iOS都參考到PCL專案,如下圖:

2015-01-08_150357

 

接著我們在PCL專案中,使用加入服務參考的方式將WebService加入參考中,
如果有成功找到服務就可以看到先前步驟中所建立的GetData方法,按下確定後加入參考。

2015-01-08_150654

2015-01-08_150846 

 

至此步驟時,
我們已經可以在Android或iOS專案中叫用加入服務參考後工具所幫我們建立出的Proxy Class,
不過我們都使用了PCL專案了,當然可以將呼叫WebService的動作也寫在PCL內,
在PCL專案中建立一個叫做MyService的類別,
並建立一個GetData方法讓它的參數與回傳值與Service上的GetData相同,如下程式碼:

{
    public class MyService
    {
        public string GetData(int value)
        {

        }
    }
}

 

在PCL的GetData方法內,就可以開始撰寫呼叫Service的程式碼片段了,
首先同樣的我們要建立出Proxy類別為Service1Client,與在一般C#使用上不同的是,
在Xamarin中預設並不支援App.config這類檔案的讀取(意指System.Configuration.*不存在),
所以我們要在建構子內傳入EndpointAddress和Binding,並在EndpointAddress內定義WebService的位置,如下程式碼:

            var address=new EndpointAddress("http://testmyws.azurewebsites.net/Service1.svc");
            Service1Client service = new Service1Client(binding, address);

建立出proxy類別後,就可以叫用服務中提供的方法了,這時你會發現,只有非同步的方法可以呼叫,如下圖:

2015-01-08_154136

 

 

沒錯,在PCL中使用建立WebService服務時,只提供非同步的方法可以使用,
而這種在呼叫方法尾部加上Async以及用來通知結果對應的方法事件名稱尾部加上Completed的方式,
稱為事件架構非同步模式(EAP,全名是Event-based Asynchronous Pattern..不用特別記~知道就好)
因此我們要在MyService中也建立一個Event供外部呼叫?
不需要這麼麻煩,在C#5.0後多了async和await關鍵字,
進而衍生出了以工作為基礎的非同步模式(TAP,Task-based Asynchronous Pattern)
因此我們可以使用TaskCompletionSource類別將EAP模式轉換成為TAP模式,如下程式碼片段:

            service.GetDataCompleted += (sender, e) =>
            {
                if (e.Cancelled)
                    task.TrySetCanceled();
                else if (e.Error != null)
                    task.TrySetException(e.Error);
                else
                    task.TrySetResult(e.Result);
            };
            service.GetDataAsync(value);
            return task.Task;

 

改為TAP模式後必須將該方法的回傳值改為Task:


 

 

 

最後我們以Android為例,建立MyService類別並且呼叫GetData方法,
因GetData回傳為Task類型,我們會用到await關鍵字,因此要在呼叫的方法也加上async關鍵字,如下:

            button.Click +=async (sender,e)=>
            {
                var result =await service.GetData(999);
                Toast.MakeText(this, result, ToastLength.Long).Show();
            };

兩個平台分別以模擬器執行的結果如圖:

2015-01-08_170809

2015-01-08_170845

 

由此處可下載範例檔案:

https://github.com/stevenchang0529/Xamarin.WebServiceDemo

 

相關參考資料:

EAP模式:http://msdn.microsoft.com/zh-tw/library/wewwczdw(v=vs.110).aspx

TAP模式:http://msdn.microsoft.com/zh-tw/library/hh873175(v=vs.110).aspx

EAP to TAP:http://msdn.microsoft.com/zh-tw/library/hh873178(v=vs.110).aspx#EAP