問題
在進行 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;
...
}