DependencyService-Registrierung und -Auflösung in Xamarin.Forms

Beispiel herunterladen Das Beispiel herunterladen

Wenn Sie die zum Aufrufen nativer Xamarin.FormsDependencyService Plattformfunktionen verwenden, müssen Plattformimplementierungen bei DependencyServiceregistriert und dann aus freigegebenem Code aufgelöst werden, um sie aufzurufen.

Registrieren von Plattformimplementierungen

Plattformimplementierungen müssen mit der DependencyService-Klasse registriert werden, damit diese in Xamarin.Forms zur Laufzeit gefunden werden können.

Die Registrierung kann mithilfe der Methoden DependencyAttribute oder Register und RegisterSingleton erfolgen.

Wichtig

Releasebuilds von UWP-Projekten, die nativen .NET-Kompilierung verwenden, sollten Plattformimplementierungen mit den Register-Methoden registrieren.

Registrierung mithilfe eines Attributs

Mithilfe von DependencyAttribute kann eine Plattformimplementierung mit der DependencyService-Klasse registriert werden. Das Attribut gibt an, dass der festgelegte Typ eine konkrete Implementierung der Schnittstelle bereitstellt.

Im folgenden Beispiel wird mithilfe von DependencyAttribute die iOS-Implementierung der IDeviceOrientationService-Schnittstelle registriert:

using Xamarin.Forms;

[assembly: Dependency(typeof(DeviceOrientationService))]
namespace DependencyServiceDemos.iOS
{
    public class DeviceOrientationService : IDeviceOrientationService
    {
        public DeviceOrientation GetOrientation()
        {
            ...
        }
    }
}

In diesem Beispiel wird DeviceOrientationService von DependencyAttribute mit der DependencyService-Klasse registriert. Dies führt dazu, dass der konkrete Typ mit der von ihm implementierten Schnittstelle registriert wird.

Gleichermaßen sollten die Implementierungen der IDeviceOrientationService-Schnittstelle auf anderen Plattformen mit der DependencyAttribute-Klasse registriert werden.

Hinweis

Die Registrierung mit DependencyAttribute erfolgt auf Namespaceebene.

Registrierung mithilfe einer Methode

Mithilfe der Methoden DependencyService.Register und der RegisterSingleton-Methode kann eine Plattformimplementierung bei DependencyService registriert werden.

Im folgenden Beispiel wird mithilfe der Register-Methode die iOS-Implementierung der IDeviceOrientationService-Schnittstelle registriert:

[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 diesem Beispiel wird mit der Register-Methode der konkrete Typ, DeviceOrientationService, für die IDeviceOrientationService-Schnittstelle registriert. Alternativ kann die Register-Methode überladen werden, um eine Plattformimplementierung mit der DependencyService-Klasse zu registrieren:

DependencyService.Register<DeviceOrientationService>();

In diesem Beispiel wird DeviceOrientationService von der Register-Methode mit der DependencyService-Klasse registriert. Dies führt dazu, dass der konkrete Typ mit der von ihm implementierten Schnittstelle registriert wird.

Alternativ kann eine vorhandene Objektinstanz mit der RegisterSingleton-Methode als Singleton registriert werden:

var service = new DeviceOrientationService();
DependencyService.RegisterSingleton<IDeviceOrientationService>(service);

Bei diesem Beispiel registriert die RegisterSingleton-Methode die Instanz des DeviceOrientationService-Objekts an der IDeviceOrientationService-Schnittstelle als Singleton.

Gleichermaßen können die Implementierungen der IDeviceOrientationService-Schnittstelle auf anderen Plattformen mit den Methoden Register und der RegisterSingleton-Methode registriert werden.

Wichtig

Die Registrierung mit den Methoden Register und der RegisterSingleton-Methode muss in Plattformprojekten erfolgen, bevor die von der Plattformimplementierung bereitgestellte Funktionalität aus dem freigegebenen Code aufgerufen wird.

Auflösen der Plattformimplementierungen

Plattformimplementierungen müssen zunächst aufgelöst werden, bevor sie aufgerufen werden. Dies erfolgt in der Regel im freigegebenen Code mithilfe der DependencyService.Get<T>-Methode. Aber auch mit der DependencyService.Resolve<T>-Methode kann dies erreicht werden.

Standardmäßig löst DependencyService nur Plattformimplementierungen auf, die parameterlose Konstruktoren besitzen. In Xamarin.Forms kann jedoch eine Methode für die Auflösung von Abhängigkeiten eingefügt werden, die für die Auflösung von Plattformimplementierungen einen Dependency Injection-Container oder Factorymethoden verwendet. Dieser Ansatz kann zur Auflösung von Plattformimplementierungen verwendet werden, die über Konstruktoren mit Parametern verfügen. Weitere Informationen finden Sie unter Auflösung von Abhängigkeiten in Xamarin.Forms.

Wichtig

Wenn eine Plattformimplementierung, die nicht mit DependencyService registriert wurde, aufgerufen wird, tritt eine NullReferenceException auf.

Auflösen mit der Get<T>-Methode

Die Get<T>-Methode ruft zur Laufzeit die Plattformimplementierung der T-Schnittstelle ab. Anschließend wird:

  • Eine Instanz davon als Singleton erstellt.
  • Eine vorhandene Instanz als Singleton zurückgegeben, die mithilfe von DependencyService durch die RegisterSingleton-Methode registriert wurde.

Diese Instanz bleibt in beiden Fällen während der gesamten Lebensdauer der Anwendung erhalten. Alle nachfolgenden Aufrufe zur Auflösung derselben Plattformimplementierung rufen dieselbe Instanz ab.

Im folgenden Code ist ein Beispiel für den Aufruf der Get<T>-Methode zur Auflösung der IDeviceOrientationService-Schnittstelle und den anschließenden Aufruf der GetOrientation-Methode dargestellt:

IDeviceOrientationService service = DependencyService.Get<IDeviceOrientationService>();
DeviceOrientation orientation = service.GetOrientation();

Alternativ kann dieser Code auf eine einzige Zeile verkürzt werden:

DeviceOrientation orientation = DependencyService.Get<IDeviceOrientationService>().GetOrientation();

Hinweis

Die Get<T>-Methode gibt standardmäßig eine Instanz der Plattformimplementierung der T-Schnittstelle als Singleton zurück. Dieses Verhalten kann jedoch geändert werden. Weitere Informationen finden Sie unter Verwalten der Lebensdauer von aufgelösten Objekten.

Auflösen mit der Resolve<T>-Methode

Die Resolve<T>-Methode ruft zur Laufzeit die Plattformimplementierung der T-Schnittstelle mithilfe einer Abhängigkeitsauflösungsmethode ab, die in Xamarin.Forms mit der DependencyResolver-Klasse eingefügt wurde. Wenn keine Abhängigkeitsauflösungsmethode in Xamarin.Forms eingefügt wurde, greift die Resolve<T>-Methode auf den Aufruf der Get<T>-Methode zurück, um die Plattformimplementierung abzurufen. Weitere Informationen zum Einfügen einer Abhängigkeitsauflösungsmethode in Xamarin.Forms finden Sie unter Abhängigkeitsauflösung in Xamarin.Forms.

Im folgenden Code ist ein Beispiel für den Aufruf der Resolve<T>-Methode zur Auflösung der IDeviceOrientationService-Schnittstelle und den anschließenden Aufruf der GetOrientation-Methode dargestellt:

IDeviceOrientationService service = DependencyService.Resolve<IDeviceOrientationService>();
DeviceOrientation orientation = service.GetOrientation();

Alternativ kann dieser Code auf eine einzige Zeile verkürzt werden:

DeviceOrientation orientation = DependencyService.Resolve<IDeviceOrientationService>().GetOrientation();

Hinweis

Wenn die Resolve<T>-Methode auf den Aufruf der Get<T>-Methode zurückgreift, wird standardmäßig eine Instanz der Plattformimplementierung der T-Schnittstelle als Singleton zurückgegeben. Dieses Verhalten kann jedoch geändert werden. Weitere Informationen finden Sie unter Verwalten der Lebensdauer von aufgelösten Objekten.

Verwalten der Lebensdauer von aufgelösten Objekten

Das Standardverhalten der DependencyService-Klasse ist die Auflösung von Plattformimplementierungen als Singletons. Daher bleiben Plattformimplementierungen während der gesamten Lebensdauer einer Anwendung erhalten.

Dieses Verhalten wird mit dem optionalen Argument DependencyFetchTarget in den Methoden Get<T> und Resolve<T> festgelegt. Die DependencyFetchTarget-Enumeration definiert zwei Elemente:

  • GlobalInstance: Die Plattformimplementierung wird als Singleton zurückgegeben.
  • NewInstance: Eine neue Instanz der Plattformimplementierung wird zurückgegeben. Die Verwaltung der Lebensdauer der Plattformimplementierungsinstanz wird dann von der Anwendung übernommen.

Die Methoden Get<T> und Resolve<T> setzen beide ihre optionalen Argumente auf DependencyFetchTarget.GlobalInstance, sodass Plattformimplementierungen immer als Singletons auflöst werden. Dieses Verhalten kann geändert werden, um neue Instanzen von Plattformimplementierungen zu erstellen, indem DependencyFetchTarget.NewInstance als Argumente für die Methoden Get<T> und Resolve<T> angegeben werden:

ITextToSpeechService service = DependencyService.Get<ITextToSpeechService>(DependencyFetchTarget.NewInstance);

In diesem Beispiel wird mit DependencyService eine neue Instanz der Plattformimplementierung für die ITextToSpeechService-Schnittstelle erstellt. Durch alle nachfolgenden Aufrufe zum Auflösen von ITextToSpeechService werden ebenfalls neue Instanzen erstellt.

Wenn immer wieder eine neue Instanz einer Plattformimplementierung erstellt wird, hat dies zur Folge, dass die Verwaltung der Lebensdauer dieser Instanzen durch die Anwendung erfolgt. Daher wird empfohlen, wenn Sie ein in einer Plattformimplementierung definiertes Ereignis abonnieren, das Ereignis wieder abzubestellen, sobald die Plattformimplementierung nicht mehr benötigt wird. Darüber hinaus kann es für Plattformimplementierungen erforderlich sein, IDisposable zu implementieren und die entsprechenden Ressourcen in Dispose-Methoden zu bereinigen. In der Beispielanwendung wird dieses Szenario in der TextToSpeechService-Plattformimplementierungen veranschaulicht.

Wenn eine Plattformimplementierung, die IDisposable implementiert, von einer Anwendung nicht mehr benötigt wird, sollte diese die Dispose-Implementierung des Objekts aufrufen. Dies kann beispielsweise mit einer using-Anweisung erreicht werden:

ITextToSpeechService service = DependencyService.Get<ITextToSpeechService>(DependencyFetchTarget.NewInstance);
using (service as IDisposable)
{
    await service.SpeakAsync("Hello world");
}

In diesem Beispiel verwirft die using-Anweisung nach dem Aufruf der SpeakAsync-Methode automatisch das Plattformimplementierungsobjekt. Dies führt dazu, dass die Dispose-Methode des Objekts aufgerufen wird, wodurch die erforderliche Bereinigung erfolgt.

Weitere Informationen zum Aufrufen der Dispose-Methode eines Objekts finden Sie unter Verwenden von Objekten, die IDisposable implementieren.