Xamarin.Form目前是微軟提供的一種跨平臺的開發(fā)技術(shù),可以讓開發(fā)者在iOS、Android和Window Phone等平臺上共享60%以上的代碼,從而節(jié)省維護(hù)多個(gè)平臺代碼的精力。但是完全不跟特定平臺的代碼打交道也是不可能的,為此,Xamarin.Form提供了一個(gè)強(qiáng)大的Api,讓開發(fā)者可以實(shí)現(xiàn)跨平臺調(diào)用代碼,這個(gè)Api就是DependencyService。
利用DependencyService,我們就可以調(diào)用特定平臺的代碼,從而可以做原生代碼所能做的任何事情。
為了在Xamarin.Form中使用DependencyService,我們需要做以下四件事情。
- 定義接口,這個(gè)接口是平臺無關(guān)的,定義了Xamarin.Form與特定平臺交互的方式。
- 編寫特定平臺上的具體實(shí)現(xiàn)。
- 通過DependencyService所提供的元標(biāo)記來注冊這些實(shí)現(xiàn),讓DependencyService在運(yùn)行時(shí)可以找到特定的實(shí)現(xiàn)類。
- 在Xamarin.Form中使用DependencyService顯式調(diào)用接口的實(shí)現(xiàn)。

定義接口
接口決定了我們在Xamarin.Form中使用平臺代碼的方式,這里我們定義一個(gè)文本轉(zhuǎn)語音的接口。
public interface ITextToSpeech {
void Speak ( string text );
}
編寫特定平臺上的實(shí)現(xiàn)
實(shí)現(xiàn)類必然要實(shí)現(xiàn)上面所定義的接口,并且必須有一個(gè)無參構(gòu)造器。
這里以iOS平臺為例。
public class TextToSpeechImplementation : ITextToSpeech
{
public TextToSpeechImplementation () {}
public void Speak (string text)
{
var speechSynthesizer = new AVSpeechSynthesizer ();
var speechUtterance = new AVSpeechUtterance (text) {
Rate = AVSpeechUtterance.MaximumSpeechRate/4,
Voice = AVSpeechSynthesisVoice.FromLanguage ("en-US"),
Volume = 0.5f,
PitchMultiplier = 1.0f
};
speechSynthesizer.SpeakUtterance (speechUtterance);
}
}
注冊實(shí)現(xiàn)
完成實(shí)現(xiàn)之后,我們還要使用[assembly]標(biāo)記來注冊他們,唯有這樣,DependencyService才能在運(yùn)行時(shí)找到接口所對應(yīng)的實(shí)現(xiàn)類。
我們要在命名空間之上添加如下代碼:
using AVFoundation;
using DependencyServiceSample.iOS;//enables registration outside of namespace
[assembly: Xamarin.Forms.Dependency (typeof (TextToSpeechImplementation))]
namespace DependencyServiceSample.iOS {
public class TextToSpeechImplementation : ITextToSpeech
......
其中,由于注冊的聲明位置在命名空間之外,所以需要在引用中添加對該命名空間的引用,否則注冊會報(bào)錯(cuò)。
將上述兩部分加在一起的實(shí)現(xiàn)類完整代碼如下:
using AVFoundation;
using DependencyServiceSample.iOS;//enables registration outside of namespace
[assembly: Xamarin.Forms.Dependency (typeof (TextToSpeechImplementation))]
namespace DependencyServiceSample.iOS {
public class TextToSpeechImplementation : ITextToSpeech
{
public TextToSpeechImplementation () {}
public void Speak (string text)
{
var speechSynthesizer = new AVSpeechSynthesizer ();
var speechUtterance = new AVSpeechUtterance (text) {
Rate = AVSpeechUtterance.MaximumSpeechRate/4,
Voice = AVSpeechSynthesisVoice.FromLanguage ("en-US"),
Volume = 0.5f,
PitchMultiplier = 1.0f
};
speechSynthesizer.SpeakUtterance (speechUtterance);
}
}
在Android平臺和Window Phone上也是如此,除了實(shí)現(xiàn)不同,其它的部分都是一樣的。這里不作贅述。
使用DependencyService
完成了上述步驟之后,我們在Xamarin.Form使用DependencyService.Get<ITextToSpeech>()就可以獲得一個(gè)ITextToSpeech實(shí)現(xiàn)類的實(shí)例對象。
具體獲得哪一個(gè)實(shí)現(xiàn)類取決于Xamarin.Form所運(yùn)行的平臺。
需要指出的是,DependencyService.Get<T>()每一次都會返回同一個(gè)對象,事實(shí)上,Get<T>()是這樣的:Get<T>(DependencyFetchTarget)。
DependencyFetchTarget是個(gè)枚舉類,
public enum DependencyFetchTarget
{
GlobalInstance,
NewInstance
}
故名思義,GlobalInstance是每次都返回同一個(gè)全局的對象,也就單例模式;而NewInstance則是每次都返回一個(gè)新的對象。而Get<T>()等價(jià)于Get<T>(DependencyFetchTarget.GlobalInstance),因此默認(rèn)是單例模式。
可以看出,DependencyService.Get<T>()是不接收其它參數(shù)類型的,這也就是為什么實(shí)現(xiàn)類必須有一個(gè)無參構(gòu)造器。
最后,代碼結(jié)構(gòu)應(yīng)該如下這般:
