XamarinForms 系列課程

特別說明

2017/01/06

Xamarin FAQ 1-004 : 如何從PCL來同步呼叫原生專案內實作方法

問題

在進行 Xamarin.Forms 專案開發的時候,必定會使用這這樣的需求,那就是有些功能在核心 PCL 專案內是無法使用的,需要在原生專案內實作出這些功能,並且,在每個不同平台的原生專案內,又需要使用不同原生專案支援的類別庫,來完成這些功能需求。這個時候,您可以使用 Prism 的相依性服務機制,在每個不同平台來實作出這些功能,透過相依性服務注入機制,在檢視模型 (ViewModels)內,使用建構式注入的方式,取得這些實作物件,如此,就可以在核心 PCL 專案內呼叫這些原生專案獨有的功能了。

解答

要解決這樣的需求,請依照底下的步驟進行操作。
  • 首先,在核心 PCL 專案內,產生一個介面 (Interface),在這個介面內宣告出共用的方法。在底下,定義了一個介面,裡面有個方法 GetPlatformName,我們期望能夠在核心 PCL 專案內呼叫這個方法,就可以知道當時是在哪個平台作業系統上執行。
    public interface INatvieAssyFile
    {
        /// <summary>
        /// 取得作業系統版本名稱
        /// </summary>
        /// <returns></returns>
        string GetPlatformName();
    }
  • 接著,您需要在每個原生平台(Android, iOS, UWP)專案中,產生一個類別,並且實作出這個介面功能。在底下的範例中,我們產生了一個 NatvieAssyFile類別,並且實作了介面 INatvieAssyFile的功能;因為這個類別是定義在 iOS 專案內,所以方法 GetPlatformName() 就僅會回傳 iOS 這個字串。
    如此,當這個 Xamarin.Forms 的專案在 iOS 系統下運行的時候,並且程式在核心 PCL 專案內執行呼叫 GetPlatformName()方法,就會得到了 iOS 這個字串;當然,您需要其他原生專案內也實作出同樣的類別,並且回傳當時作業系統的文字。
  • 另外,您需要在 namespace 前面,宣告這個類別可以具備相依性服務注入的能力,在這個範例中,使用了這樣的語法 [assembly: Xamarin.Forms.Dependency(typeof(NatvieAssyFile))]。加入了這行,您就可以在核心 PCL 專案內,使用建構式注入的方式,取得這個實作物件了。
[assembly: Xamarin.Forms.Dependency(typeof(NatvieAssyFile))]
namespace XFFiles.iOS.Services
{
    class NatvieAssyFile : INatvieAssyFile
    {
        public string GetPlatformName()
        {
            return "iOS";
        }
    }
}
  • 最後,我們來看如何在核心 PCL 專案內,取得這個注入物件;要做到取得注入物件,請參考底下步驟:
    • 宣告一個 INatvieAssyFile 介面變數,用來持有注入後的實作物件。
    • 在檢視模型的建構式中,加入這個引數 INatvieAssyFile natvieAssyFile
    • 在檢視模型的建構式裡面,將剛剛注入進來的物件,設定讓欄位變數可以持有這個傳入的物件。
        private readonly INavigationService _navigationService;
        private readonly INatvieAssyFile _natvieAssyFile;
        #endregion

        #region Constructor 建構式
        public MainPageViewModel(INavigationService navigationService, INatvieAssyFile natvieAssyFile)
        {

            _navigationService = navigationService;
            _natvieAssyFile = natvieAssyFile;
            ...
        }

沒有留言:

張貼留言