Xamarin.Forms Registrazione e risoluzione di DependencyService
Quando si Xamarin.FormsDependencyService
usa per richiamare la funzionalità della piattaforma nativa, le implementazioni della DependencyService
piattaforma devono essere registrate con e quindi risolte dal codice condiviso per richiamarle.
Registrare le implementazioni della piattaforma
Le implementazioni della piattaforma devono essere registrate con in DependencyService
modo che Xamarin.Forms possano individuarle in fase di esecuzione.
La registrazione può essere eseguita con , DependencyAttribute
o con i Register
metodi e RegisterSingleton
.
Importante
Le build di versione dei progetti UWP che usano la compilazione .NET nativa devono registrare le implementazioni della piattaforma con i metodi Register
.
Registrazione in base all'attributo
È possibile usare DependencyAttribute
per registrare un'implementazione della piattaforma con DependencyService
. L'attributo indica che il tipo specificato offre un'implementazione concreta dell'interfaccia.
L'esempio seguente usa per DependencyAttribute
registrare l'implementazione iOS dell'interfaccia IDeviceOrientationService
:
using Xamarin.Forms;
[assembly: Dependency(typeof(DeviceOrientationService))]
namespace DependencyServiceDemos.iOS
{
public class DeviceOrientationService : IDeviceOrientationService
{
public DeviceOrientation GetOrientation()
{
...
}
}
}
In questo esempio, DependencyAttribute
registra DeviceOrientationService
con DependencyService
. Il tipo concreto viene quindi registrato per l'interfaccia che implementa.
Analogamente, le implementazioni dell'interfaccia IDeviceOrientationService
in altre piattaforme devono essere registrate con DependencyAttribute
.
Nota
La registrazione con DependencyAttribute
viene eseguita a livello di spazio dei nomi.
Registrazione in base al metodo
I DependencyService.Register
metodi e il RegisterSingleton
metodo possono essere usati per registrare un'implementazione della piattaforma con .DependencyService
Nell'esempio seguente viene usato il Register
metodo per registrare l'implementazione iOS dell'interfaccia IDeviceOrientationService
:
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
DependencyService.Register<IDeviceOrientationService, DeviceOrientationService>();
return base.FinishedLaunching(app, options);
}
}
In questo esempio, il metodo Register
registra il tipo concreto DeviceOrientationService
per l'interfaccia IDeviceOrientationService
. In alternativa è possibile usare un overload del metodo Register
per registrare un'implementazione della piattaforma con DependencyService
:
DependencyService.Register<DeviceOrientationService>();
In questo esempio, il metodo Register
registra DeviceOrientationService
con DependencyService
. Il tipo concreto viene quindi registrato per l'interfaccia che implementa.
In alternativa, un'istanza di oggetto esistente può essere registrata come singleton con il RegisterSingleton
metodo :
var service = new DeviceOrientationService();
DependencyService.RegisterSingleton<IDeviceOrientationService>(service);
In questo esempio il RegisterSingleton
metodo registra l'istanza dell'oggetto DeviceOrientationService
sull'interfaccia IDeviceOrientationService
, come singleton.
Analogamente, le implementazioni dell'interfaccia IDeviceOrientationService
in altre piattaforme possono essere registrate con i Register
metodi o il RegisterSingleton
metodo .
Importante
La registrazione con i Register
metodi e RegisterSingleton
deve essere eseguita nei progetti di piattaforma, prima che la funzionalità fornita dall'implementazione della piattaforma venga richiamata dal codice condiviso.
Risolvere le implementazioni della piattaforma
Le implementazioni della piattaforma devono essere risolte prima di essere richiamate. Questa operazione viene in genere eseguita nel codice condiviso tramite il metodo DependencyService.Get<T>
. Tuttavia, può essere eseguita anche con il metodo DependencyService.Resolve<T>
.
Per impostazione predefinita, la classe DependencyService
risolverà solo le implementazioni della piattaforma che hanno costruttori senza parametri. Tuttavia, un metodo di risoluzione delle dipendenze può essere inserito in Xamarin.Forms che usa un contenitore di inserimento delle dipendenze o metodi factory per risolvere le implementazioni della piattaforma. Questo approccio può essere usato per risolvere le implementazioni della piattaforma che hanno costruttori con parametri. Per altre informazioni, vedere Risoluzione delle dipendenze in Xamarin.Forms.
Importante
Se si richiama un'implementazione della piattaforma che non è stata registrata con DependencyService
verrà generata una NullReferenceException
.
Risolvere con il metodo Get<T>
Il Get<T>
metodo recupera l'implementazione della piattaforma dell'interfaccia T
in fase di esecuzione e:
- Crea un'istanza di come singleton.
- Restituisce un'istanza esistente come singleton, registrata con il
DependencyService
RegisterSingleton
metodo .
In entrambi i casi, l'istanza sarà attiva per la durata dell'applicazione e tutte le chiamate successive per risolvere la stessa implementazione della piattaforma recupereranno la stessa istanza.
Il codice seguente mostra un esempio della chiamata del metodo Get<T>
per risolvere l'interfaccia IDeviceOrientationService
e della chiamata del relativo metodo GetOrientation
:
IDeviceOrientationService service = DependencyService.Get<IDeviceOrientationService>();
DeviceOrientation orientation = service.GetOrientation();
Questo codice può essere in alternativa compresso in una singola riga:
DeviceOrientation orientation = DependencyService.Get<IDeviceOrientationService>().GetOrientation();
Nota
Il Get<T>
metodo restituisce un'istanza dell'implementazione della piattaforma dell'interfaccia T
come singleton, per impostazione predefinita. Tuttavia, è possibile modificare questo comportamento. Per altre informazioni, vedere Gestire la durata degli oggetti risolti.
Risolvere con il metodo Resolve<T>
Il Resolve<T>
metodo recupera l'implementazione della piattaforma dell'interfaccia T
in fase di esecuzione, usando un metodo di risoluzione delle dipendenze inserito Xamarin.Forms nella DependencyResolver
classe . Se un metodo di risoluzione delle dipendenze non è stato inserito in Xamarin.Forms, il metodo eseguirà il Resolve<T>
fallback alla chiamata del Get<T>
metodo per recuperare l'implementazione della piattaforma. Per altre informazioni sull'inserimento di un metodo di risoluzione delle dipendenze in Xamarin.Forms, vedere Risoluzione delle dipendenze in Xamarin.Forms.
Il codice seguente mostra un esempio della chiamata del metodo Resolve<T>
per risolvere l'interfaccia IDeviceOrientationService
e della chiamata del relativo metodo GetOrientation
:
IDeviceOrientationService service = DependencyService.Resolve<IDeviceOrientationService>();
DeviceOrientation orientation = service.GetOrientation();
Questo codice può essere in alternativa compresso in una singola riga:
DeviceOrientation orientation = DependencyService.Resolve<IDeviceOrientationService>().GetOrientation();
Nota
Quando il metodo esegue il Resolve<T>
fallback alla chiamata al Get<T>
metodo , restituisce un'istanza dell'implementazione della piattaforma dell'interfaccia T
come singleton, per impostazione predefinita. Tuttavia, è possibile modificare questo comportamento. Per altre informazioni, vedere Gestire la durata degli oggetti risolti.
Gestire la durata degli oggetti risolti
Il comportamento predefinito della classe DependencyService
prevede la risoluzione delle implementazioni della piattaforma come singleton. Di conseguenza, le implementazioni della piattaforma avranno la stessa durata di un'applicazione.
Questo comportamento viene specificato con l'argomento facoltativo DependencyFetchTarget
per i metodi Get<T>
e Resolve<T>
. L'enumerazione DependencyFetchTarget
definisce due membri:
GlobalInstance
, che restituisce l'implementazione della piattaforma come singleton.NewInstance
, che restituisce una nuova istanza dell'implementazione della piattaforma. L'applicazione è quindi responsabile della gestione della durata dell'istanza dell'implementazione della piattaforma.
Entrambi i metodi Get<T>
e Resolve<T>
impostano i relativi argomenti facoltativi su DependencyFetchTarget.GlobalInstance
e quindi le implementazioni della piattaforma vengono sempre risolte come singleton. Questo comportamento può essere modificato, in modo che vengano create nuove istanze delle implementazioni della piattaforma, specificando DependencyFetchTarget.NewInstance
come argomenti per i metodi Get<T>
e Resolve<T>
:
ITextToSpeechService service = DependencyService.Get<ITextToSpeechService>(DependencyFetchTarget.NewInstance);
In questo esempio, DependencyService
crea una nuova istanza dell'implementazione della piattaforma per l'interfaccia ITextToSpeechService
. Anche tutte le chiamate successive per risolvere ITextToSpeechService
creeranno nuove istanze.
La conseguenza di creare sempre una nuova istanza di un'implementazione della piattaforma è che l'applicazione diventa responsabile della gestione della durata delle istanze. Questo significa che se si sottoscrive un evento definito in un'implementazione della piattaforma, è necessario annullare la sottoscrizione dall'evento quando l'implementazione della piattaforma non è più necessaria. Significa anche che potrebbe essere necessario per le implementazioni della piattaforma implementare IDisposable
e gestire la pulizia delle relative risorse nei metodi Dispose
. L'applicazione di esempio illustra questo scenario nelle implementazioni della piattaforma TextToSpeechService
.
Quando un'applicazione termina l'uso di un'implementazione della piattaforma che implementa IDisposable
, deve chiamare l'implementazione Dispose
dell'oggetto. Un modo per ottenere questo risultato è un'istruzione using
:
ITextToSpeechService service = DependencyService.Get<ITextToSpeechService>(DependencyFetchTarget.NewInstance);
using (service as IDisposable)
{
await service.SpeakAsync("Hello world");
}
In questo esempio, dopo la chiamata del metodo SpeakAsync
, l'istruzione using
elimina automaticamente l'oggetto implementazione della piattaforma. Il risultato è la chiamata del metodo Dispose
dell'oggetto, che esegue la pulizia necessaria.
Per altre informazioni sulla chiamata del metodo Dispose
di un oggetto, vedere Uso di oggetti che implementano IDisposable.