Xamarin.Forms Rejestracja i rozwiązywanie problemów usługi DependencyService

Download Sample Pobieranie przykładu

W przypadku używania Xamarin.FormsDependencyService elementu do wywoływania natywnej funkcji platformy implementacje platformy muszą być zarejestrowane w obiekcie , a następnie rozpoznawane z udostępnionego DependencyServicekodu w celu ich wywołania.

Rejestrowanie implementacji platformy

Implementacje platformy muszą być zarejestrowane w obiekcie DependencyService , aby Xamarin.Forms można je było zlokalizować w czasie wykonywania.

Rejestrację DependencyAttributemożna wykonać za pomocą metody , lub z Register metodami i RegisterSingleton .

Ważne

Kompilacje wydania projektów platformy UWP, które korzystają z natywnej kompilacji platformy .NET, powinny rejestrować implementacje platformy przy użyciu Register metod .

Rejestracja według atrybutu

Można DependencyAttribute go użyć do zarejestrowania implementacji platformy w programie DependencyService. Atrybut wskazuje, że określony typ zapewnia konkretną implementację interfejsu.

W poniższym przykładzie użyto elementu , DependencyAttribute aby zarejestrować implementację interfejsu dla IDeviceOrientationService systemu iOS:

using Xamarin.Forms;

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

W tym przykładzie element rejestruje element DependencyAttributeDeviceOrientationService za pomocą elementu DependencyService. Powoduje to zarejestrowanie konkretnego typu względem interfejsu, który implementuje.

Podobnie implementacje interfejsu IDeviceOrientationService na innych platformach powinny być zarejestrowane w programie DependencyAttribute.

Uwaga

Rejestracja za pomocą elementu DependencyAttribute jest wykonywana na poziomie przestrzeni nazw.

Rejestracja według metody

Metody DependencyService.Register i RegisterSingleton metoda mogą służyć do rejestrowania implementacji platformy za pomocą metody DependencyService.

W poniższym przykładzie użyto Register metody do zarejestrowania implementacji interfejsu systemu IDeviceOrientationService iOS:

[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);
    }
}

W tym przykładzie Register metoda rejestruje typ betonu , DeviceOrientationServicewzględem interfejsu IDeviceOrientationService . Alternatywnie można użyć przeciążenia Register metody do zarejestrowania implementacji platformy za pomocą metody DependencyService:

DependencyService.Register<DeviceOrientationService>();

W tym przykładzie Register metoda rejestruje DeviceOrientationService element za pomocą metody DependencyService. Powoduje to zarejestrowanie konkretnego typu względem interfejsu, który implementuje.

Alternatywnie istniejące wystąpienie obiektu można zarejestrować jako pojedyncze wystąpienie za pomocą RegisterSingleton metody :

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

W tym przykładzie RegisterSingleton metoda rejestruje DeviceOrientationService wystąpienie obiektu względem interfejsu IDeviceOrientationService jako pojedyncze.

Podobnie implementacje interfejsu IDeviceOrientationService na innych platformach można zarejestrować za Register pomocą metod lub RegisterSingleton metody .

Ważne

Rejestracja za Register pomocą metod i RegisterSingleton musi być wykonywana w projektach platformy, zanim funkcja udostępniona przez implementację platformy zostanie wywołana z kodu udostępnionego.

Rozwiązywanie problemów z implementacjami platformy

Przed wywołaniem należy rozwiązać implementacje platformy. Jest to zwykle wykonywane w kodzie udostępnionym DependencyService.Get<T> przy użyciu metody . Można go jednak również wykonać za DependencyService.Resolve<T> pomocą metody .

Domyślnie obiekt DependencyService będzie rozpoznawał tylko implementacje platformy, które mają konstruktory bez parametrów. Można jednak wstawić metodę rozwiązywania zależności, która używa kontenera iniekcji Xamarin.Forms zależności lub metod fabryki do rozwiązywania implementacji platformy. Takie podejście może służyć do rozwiązywania implementacji platformy, które mają konstruktory z parametrami. Aby uzyskać więcej informacji, zobacz Rozwiązywanie zależności w programie Xamarin.Forms.

Ważne

Wywoływanie implementacji platformy, która nie została zarejestrowana w obiekcie DependencyService , spowoduje NullReferenceException zgłoszenie.

Rozwiązywanie problemów przy użyciu metody Get<T>

Metoda Get<T> pobiera implementację interfejsu T platformy w czasie wykonywania i jedną z następujących metod:

  • Tworzy wystąpienie jako pojedyncze wystąpienie.
  • Zwraca istniejące wystąpienie jako pojedyncze wystąpienie, które zostało zarejestrowane przy DependencyService użyciu RegisterSingleton metody .

W obu przypadkach wystąpienie będzie aktywne przez cały okres istnienia aplikacji, a wszystkie kolejne wywołania w celu rozwiązania tej samej implementacji platformy będą pobierać to samo wystąpienie.

Poniższy kod przedstawia przykład wywołania Get<T> metody w celu rozpoznania interfejsu IDeviceOrientationService , a następnie wywołania jej GetOrientation metody:

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

Alternatywnie ten kod można skondensować w jednym wierszu:

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

Uwaga

Metoda Get<T> zwraca domyślnie wystąpienie implementacji interfejsu platformy T jako pojedyncze. Można jednak zmienić to zachowanie. Aby uzyskać więcej informacji, zobacz Zarządzanie okresem istnienia rozpoznanych obiektów.

Rozwiązywanie problemów przy użyciu metody Resolve<T>

Metoda Resolve<T> pobiera implementację platformy interfejsu T w czasie wykonywania przy użyciu metody rozwiązywania zależności, która została wstrzyknięta do Xamarin.FormsDependencyResolver klasy . Jeśli metoda rozwiązywania zależności nie została wstrzyknięta do Xamarin.Formsmetody , Resolve<T> metoda wróci do wywołania Get<T> metody w celu pobrania implementacji platformy. Aby uzyskać więcej informacji na temat wstrzykiwania metody rozwiązywania zależności do Xamarin.Formsprogramu , zobacz Rozwiązywanie zależności w pliku Xamarin.Forms.

Poniższy kod przedstawia przykład wywołania Resolve<T> metody w celu rozpoznania interfejsu IDeviceOrientationService , a następnie wywołania jej GetOrientation metody:

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

Alternatywnie ten kod można skondensować w jednym wierszu:

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

Uwaga

Resolve<T> Gdy metoda powraca do wywoływania Get<T> metody, zwraca domyślnie wystąpienie implementacji platformy interfejsu T jako pojedynczego. Można jednak zmienić to zachowanie. Aby uzyskać więcej informacji, zobacz Zarządzanie okresem istnienia rozpoznanych obiektów.

Zarządzanie okresem istnienia rozpoznanych obiektów

Domyślnym zachowaniem DependencyService klasy jest rozpoznawanie implementacji platformy jako pojedynczych dysków. W związku z tym implementacje platform będą żyć przez cały okres istnienia aplikacji.

To zachowanie jest określane z opcjonalnym argumentem DependencyFetchTargetGet<T> metod i Resolve<T> . Wyliczenie DependencyFetchTarget definiuje dwa elementy członkowskie:

  • GlobalInstance, który zwraca implementację platformy jako pojedynczą.
  • NewInstance, które zwraca nowe wystąpienie implementacji platformy. Aplikacja jest następnie odpowiedzialna za zarządzanie okresem istnienia wystąpienia implementacji platformy.

Metody Get<T> i Resolve<T> ustawiają opcjonalne argumenty na DependencyFetchTarget.GlobalInstance, a więc implementacje platformy są zawsze rozpoznawane jako pojedyncze. To zachowanie można zmienić, aby nowe wystąpienia implementacji platformy zostały utworzone, określając DependencyFetchTarget.NewInstance jako argumenty metody Get<T> i Resolve<T> :

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

W tym przykładzie zostanie DependencyService utworzone nowe wystąpienie implementacji platformy dla interfejsu ITextToSpeechService . Wszystkie kolejne wywołania, aby rozwiązać ten problem, również spowodują ITextToSpeechService utworzenie nowych wystąpień.

Konsekwencją zawsze tworzenia nowego wystąpienia implementacji platformy jest to, że aplikacja staje się odpowiedzialna za zarządzanie okresem istnienia wystąpień. Oznacza to, że jeśli subskrybujesz zdarzenie zdefiniowane w implementacji platformy, należy anulować subskrypcję zdarzenia, gdy implementacja platformy nie jest już wymagana. Ponadto oznacza to, że może być konieczne zaimplementowanie implementacji platformy IDisposablei oczyszczenie ich zasobów w Dispose metodach. Przykładowa aplikacja demonstruje ten scenariusz we TextToSpeechService wdrożeniach platformy.

Gdy aplikacja zakończy korzystanie z implementacji platformy, która implementuje IDisposableelement , powinna wywołać implementację Dispose obiektu. Jednym ze sposobów osiągnięcia tego jest using instrukcja:

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

W tym przykładzie po wywołaniu SpeakAsyncusing metody instrukcja automatycznie usuwa obiekt implementacji platformy. Spowoduje to wywołanie metody obiektu Dispose , która wykonuje wymagane czyszczenie.

Aby uzyskać więcej informacji na temat wywoływania metody obiektu Dispose , zobacz Using objects that implement IDisposable (Używanie obiektów implementujących funkcję IDisposable).