Xamarin.Forms Registrazione e risoluzione di DependencyService

Download Sample Scaricare l'esempio

Quando si Xamarin.FormsDependencyService usa per richiamare la funzionalità della piattaforma nativa, le implementazioni della DependencyServicepiattaforma 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 , DependencyAttributeo 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 DependencyServiceRegisterSingleton 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.