Регистрация и разрешение класса Xamarin.Forms DependencyService
При использовании Xamarin.FormsDependencyService
функции собственной платформы реализация платформы должна быть зарегистрирована в DependencyService
, а затем разрешена из общего кода для их вызова.
Регистрация реализаций платформы
Реализации платформы должны быть зарегистрированы в DependencyService
, чтобы платформа Xamarin.Forms могла их обнаруживать во время выполнения.
Регистрацию можно выполнить с помощью DependencyAttribute
или методов Register
и RegisterSingleton
.
Внимание
Сборки выпуска проектов универсальной платформы Windows, использующие компиляцию в собственный код .NET, должны регистрировать реализации платформы с помощью методов Register
.
Регистрация с помощью атрибута
Можно использовать DependencyAttribute
, чтобы зарегистрировать реализацию платформы в DependencyService
. Атрибут указывает, что заданный тип предоставляет конкретную реализацию интерфейса.
В следующем примере используется DependencyAttribute
для регистрации реализации интерфейса IDeviceOrientationService
для iOS.
using Xamarin.Forms;
[assembly: Dependency(typeof(DeviceOrientationService))]
namespace DependencyServiceDemos.iOS
{
public class DeviceOrientationService : IDeviceOrientationService
{
public DeviceOrientation GetOrientation()
{
...
}
}
}
В этом примере DependencyAttribute
регистрирует DeviceOrientationService
в DependencyService
. Это приводит к регистрации конкретного типа с интерфейсом, который он реализует.
Аналогичным образом реализации интерфейса IDeviceOrientationService
на других платформах должны быть зарегистрированы с помощью DependencyAttribute
.
Примечание.
Регистрация с помощью DependencyAttribute
выполняется на уровне пространства имен.
Регистрация с помощью метода
Вы можете использовать методы DependencyService.Register
и RegisterSingleton
, чтобы зарегистрировать реализацию платформы в DependencyService
.
В следующем примере используется метод Register
для регистрации реализации интерфейса 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);
}
}
В этом примере метод Register
регистрирует конкретный тип DeviceOrientationService
с интерфейсом IDeviceOrientationService
. Таким же образом можно использовать перегрузку метода Register
, чтобы зарегистрировать реализацию платформы в DependencyService
.
DependencyService.Register<DeviceOrientationService>();
В этом примере Register
регистрирует DeviceOrientationService
в DependencyService
. Это приводит к регистрации конкретного типа с интерфейсом, который он реализует.
Кроме того, можно зарегистрировать отдельный существующий экземпляр объекта с помощью метода RegisterSingleton
:
var service = new DeviceOrientationService();
DependencyService.RegisterSingleton<IDeviceOrientationService>(service);
В этом примере метод RegisterSingleton
регистрирует отдельный экземпляр объекта DeviceOrientationService
с интерфейсом IDeviceOrientationService
.
Аналогичным образом реализации интерфейса IDeviceOrientationService
на других платформах можно зарегистрировать с помощью методов Register
или RegisterSingleton
.
Внимание
Регистрация с помощью методов Register
и RegisterSingleton
должна выполняться в проектах платформы до того, как функции, предоставляемые реализацией платформы, будут вызваны из общего кода.
Разрешение реализаций платформы
Реализации платформы необходимо разрешить до их вызова. Обычно это делается в общем коде с помощью метода DependencyService.Get<T>
. Это также можно сделать с помощью метода DependencyService.Resolve<T>
.
По умолчанию DependencyService
разрешает только зависящие от платформы реализации с конструкторами без параметров. Однако в Xamarin.Forms можно внедрить метод разрешения зависимостей, который разрешает зависящие от платформы реализации с помощью контейнера внедрения зависимостей или фабричных методов. Такой подход позволяет разрешать зависящие от платформы реализации, имеющие конструкторы с параметрами. Дополнительные сведения см. в статье Разрешение зависимостей в Xamarin.Forms.
Внимание
Вызов реализации платформы, которая не была зарегистрирована с помощью DependencyService
приведет к возникновению NullReferenceException
.
Разрешение с помощью метода Get<T>
Метод Get<T>
извлекает реализуемый платформой интерфейс T
во время выполнения и:
- либо создает его отдельный экземпляр;
- либо возвращает отдельный существующий экземпляр, зарегистрированный с помощью
DependencyService
методомRegisterSingleton
.
В обоих случаях этот экземпляр существует в течение всего времени существования приложения и его будут получать все последующие вызовы для разрешения той же реализации платформы.
Следующий пример кода демонстрирует вызов метода Get<T>
для разрешения интерфейса IDeviceOrientationService
и последующего вызова его метода GetOrientation
:
IDeviceOrientationService service = DependencyService.Get<IDeviceOrientationService>();
DeviceOrientation orientation = service.GetOrientation();
Этот код можно сократить до одной строки:
DeviceOrientation orientation = DependencyService.Get<IDeviceOrientationService>().GetOrientation();
Примечание.
По умолчанию метод Get<T>
возвращает отдельный экземпляр интерфейса T
, реализуемого платформой. Хотя это можно изменить. Дополнительные сведения см. в разделе Управлении временем существования разрешенных объектов.
Разрешение с помощью метода Resolve<T>
Метод Resolve<T>
извлекает интерфейс T
, реализуемый платформой во время выполнения, используя метод разрешения зависимостей, который внедряется в Xamarin.Forms с помощью класса DependencyResolver
. Если метод разрешения зависимостей не был внедрен в Xamarin.Forms, метод Resolve<T>
переключается на вызов метода Get<T>
, чтобы извлечь реализацию платформы. Дополнительные сведения о внедрении метода разрешения зависимостей в Xamarin.Forms см. в статье о разрешении зависимостей в Xamarin.Forms.
Следующий пример кода демонстрирует вызов метода Resolve<T>
для разрешения интерфейса IDeviceOrientationService
и последующего вызова его метода GetOrientation
:
IDeviceOrientationService service = DependencyService.Resolve<IDeviceOrientationService>();
DeviceOrientation orientation = service.GetOrientation();
Этот код можно сократить до одной строки:
DeviceOrientation orientation = DependencyService.Resolve<IDeviceOrientationService>().GetOrientation();
Примечание.
Когда метод Resolve<T>
переключается на вызов метода Get<T>
, он по умолчанию возвращает отдельный экземпляр интерфейса T
, реализуемого платформой. Хотя это можно изменить. Дополнительные сведения см. в разделе Управлении временем существования разрешенных объектов.
Управлении временем существования разрешенных объектов
По умолчанию класс DependencyService
разрешает отдельную реализацию платформы. Таким образом, реализации платформы будут существовать в течение всего срока существования приложения.
Такое поведение определяется необязательным аргументом DependencyFetchTarget
в методах Get<T>
и Resolve<T>
. Перечисление DependencyFetchTarget
определяет два члена:
GlobalInstance
, который возвращает отдельную реализацию платформы;NewInstance
, который возвращает новый экземпляр реализации платформы. После этого управление временем существования экземпляра реализации платформы передается приложению.
Методы Get<T>
и Resolve<T>
назначают DependencyFetchTarget.GlobalInstance
свои необязательные аргументы, поэтому всегда разрешаются отдельные экземпляры реализаций платформы. Это поведение можно изменить так, чтобы создавались новые экземпляры реализаций платформы, указав DependencyFetchTarget.NewInstance
в качестве аргументов в методах Get<T>
и Resolve<T>
.
ITextToSpeechService service = DependencyService.Get<ITextToSpeechService>(DependencyFetchTarget.NewInstance);
В этом примере DependencyService
создает новый экземпляр реализации платформы для интерфейса ITextToSpeechService
. Все последующие вызовы для разрешения ITextToSpeechService
будут также создавать новые экземпляры.
В результате постоянного создания новых экземпляров реализации платформы управление временем существования экземпляров передается приложению. Следовательно, если вы подписаны на событие, определяемое в реализации платформы, вы должны отменить подписку на него, когда реализация платформы больше не требуется. Кроме того, это означает, что реализациям платформы может потребоваться реализация IDisposable
и очистка своих ресурсов с помощью методов Dispose
. Пример приложения демонстрирует этот сценарий с реализациями платформы TextToSpeechService
.
Когда приложение завершает использование реализации платформы, реализующей IDisposable
, оно должно вызывать реализацию Dispose
объекта. Один из способов сделать это — воспользоваться инструкцией using
.
ITextToSpeechService service = DependencyService.Get<ITextToSpeechService>(DependencyFetchTarget.NewInstance);
using (service as IDisposable)
{
await service.SpeakAsync("Hello world");
}
В этом примере после вызова метода SpeakAsync
инструкция using
автоматически удаляет объект реализации платформы. Это приводит к вызову метода Dispose
объекта, который выполняет необходимую очистку.
Дополнительные сведения о вызове метода Dispose
объекта см. в статье Использование объектов, реализующих IDisposable.