Compartilhar via


Xamarin.Forms Registro e resolução de DependencyService

Ao usar a Xamarin.FormsDependencyService funcionalidade de plataforma nativa para invocar, as implementações de plataforma devem ser registradas com o DependencyServicee, em seguida, resolvidas do código compartilhado para invocá-las.

Registrar as implementações de plataforma

As implementações da plataforma devem ser registradas no DependencyService para que Xamarin.Forms possam localizá-las em tempo de execução.

O registro pode ser realizado com o DependencyAttribute, ou com os Register métodos and RegisterSingleton .

Importante

Os builds de versão de projetos da UWP que usam a compilação nativa do .NET devem registrar implementações de plataforma com os métodos Register.

Registro por atributo

O DependencyAttribute pode ser usado para registrar uma implementação de plataforma com o DependencyService. O atributo indica que o tipo especificado fornece uma implementação concreta da interface.

O exemplo a seguir usa o DependencyAttribute para registrar a implementação iOS da IDeviceOrientationService interface:

using Xamarin.Forms;

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

Neste exemplo, o DependencyAttribute registra o DeviceOrientationService com o DependencyService. Isso resulta no tipo concreto que está sendo registrado em relação à interface que ele implementa.

Da mesma forma, as implementações da interface IDeviceOrientationService em outras plataformas devem ser registradas com o DependencyAttribute.

Observação

O registro com o DependencyAttribute é executado no nível do namespace.

Registro por método

Os DependencyService.Register métodos, e o RegisterSingleton método, podem ser usados para registrar uma implementação de plataforma com o DependencyService.

O exemplo a seguir usa o Register método para registrar a implementação iOS da IDeviceOrientationService interface:

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

Neste exemplo, o método Register registra o tipo concreto, DeviceOrientationService, na interface IDeviceOrientationService. Como alternativa, uma sobrecarga do método Register pode ser usada para registrar uma implementação de plataforma com o DependencyService:

DependencyService.Register<DeviceOrientationService>();

Neste exemplo, o método Register registra o DeviceOrientationService com o DependencyService. Isso resulta no tipo concreto que está sendo registrado em relação à interface que ele implementa.

Como alternativa, uma instância de objeto existente pode ser registrada como um singleton com o RegisterSingleton método:

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

Neste exemplo, o RegisterSingleton método registra a instância do DeviceOrientationService IDeviceOrientationService objeto na interface, como um singleton.

Da mesma forma, as implementações da IDeviceOrientationService interface em outras plataformas podem ser registradas com os Register métodos ou o RegisterSingleton método.

Importante

O registro com os Register métodos and RegisterSingleton deve ser executado em projetos de plataforma, antes que a funcionalidade fornecida pela implementação da plataforma seja invocada do código compartilhado.

Resolver as implementações da plataforma

As implementações de plataforma devem ser resolvidas antes de serem invocadas. Isso normalmente é feito no código compartilhado, usando o método DependencyService.Get<T>. No entanto, isso também pode ser realizado com o método DependencyService.Resolve<T>.

Por padrão, o DependencyService resolverá somente as implementações de plataforma que têm construtores sem parâmetros. No entanto, um método de resolução de dependência pode ser injetado que Xamarin.Forms usa um contêiner de injeção de dependência ou métodos de fábrica para resolver implementações de plataforma. Essa abordagem pode ser usada para resolver implementações da plataforma que têm construtores com parâmetros. Para obter mais informações, consulte Resolução de dependência no Xamarin.Forms.

Importante

Invocar uma implementação de plataforma que ainda não foi registrada com o DependencyService resultará na geração de uma NullReferenceException.

Resolver usando o método Get<T>

O Get<T> método recupera a implementação da plataforma da interface T em tempo de execução e:

  • Cria uma instância dele como um singleton.
  • Retorna uma instância existente como um singleton, que foi registrada com o DependencyService método by RegisterSingleton .

Em ambos os casos, a instância permanecerá durante o tempo de vida do aplicativo e todas as chamadas subsequentes para resolver a mesma implementação de plataforma recuperarão a mesma instância.

O código a seguir mostra um exemplo de chamada ao método Get<T> para resolver a interface IDeviceOrientationService e, em seguida, invocação de seu método GetOrientation:

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

Como alternativa, esse código pode ser condensado em uma única linha:

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

Observação

O Get<T> método retorna uma instância da implementação da plataforma de interface T como um singleton, por padrão. No entanto, esse comportamento pode ser alterado. Para obter mais informações, confira Gerenciar o tempo de vida de objetos resolvidos.

Resolver usando o método Resolve<T>

O Resolve<T> método recupera a implementação da plataforma da interface T em runtime, usando um método de resolução de dependência que foi injetado com Xamarin.Forms a DependencyResolver classe. Se um método de resolução de dependência não tiver sido injetado no Xamarin.Forms, o Resolve<T> método voltará a chamar o Get<T> método para recuperar a implementação da plataforma. Para obter mais informações sobre como injetar um método de resolução de dependência no Xamarin.Forms, consulte Resolução de dependência no Xamarin.Forms.

O código a seguir mostra um exemplo de chamada ao método Resolve<T> para resolver a interface IDeviceOrientationService e, em seguida, invocação de seu método GetOrientation:

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

Como alternativa, esse código pode ser condensado em uma única linha:

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

Observação

Quando o Resolve<T> método volta a chamar o Get<T> método, ele retorna uma instância da implementação da plataforma de interface T como um singleton, por padrão. No entanto, esse comportamento pode ser alterado. Para obter mais informações, confira Gerenciar o tempo de vida de objetos resolvidos.

Gerenciar o tempo de vida de objetos resolvidos

O comportamento padrão da classe DependencyService é resolver as implementações de plataforma como singletons. Portanto, as implementações de plataforma deverão durar o tempo de vida de um aplicativo.

Esse comportamento é especificado com o argumento opcional DependencyFetchTarget nos métodos Get<T> e Resolve<T>. A enumeração DependencyFetchTarget define dois membros:

  • GlobalInstance, que retorna a implementação de plataforma como um singleton.
  • NewInstance, que retorna uma nova instância da implementação de plataforma. O aplicativo, então, é responsável por gerenciar o tempo de vida da instância de implementação de plataforma.

Os métodos Get<T> e Resolve<T> definem seus argumentos opcionais como DependencyFetchTarget.GlobalInstance e, portanto, as implementações de plataforma são sempre resolvidas como singletons. Esse comportamento pode ser alterado para que novas instâncias de implementações de plataforma sejam criadas por meio da especificação de DependencyFetchTarget.NewInstance como argumentos para os métodos Get<T> e Resolve<T>:

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

Neste exemplo, o DependencyService cria uma nova instância da implementação de plataforma para a interface ITextToSpeechService. Todas as chamadas subsequentes para resolver o ITextToSpeechService também criarão novas instâncias.

A consequência de sempre criar uma nova instância de uma implementação de plataforma é que o aplicativo se torna responsável por gerenciar o tempo de vida das instâncias. Isso significa que, se você assinar um evento definido em uma implementação de plataforma, deverá cancelar o evento quando a implementação de plataforma não for mais necessária. Além disso, isso significa que talvez seja necessário que as implementações de plataforma implementem IDisposable e limpem seus recursos em métodos Dispose. O aplicativo de exemplo demonstra esse cenário em suas implementações de plataforma TextToSpeechService.

Quando um aplicativo terminar de usar uma implementação de plataforma que implementa IDisposable, ele deverá chamar a implementação Dispose do objeto. Uma maneira de realizar isso é com uma instrução using:

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

Neste exemplo, depois que o método SpeakAsync é invocado, a instrução using automaticamente descarta o objeto de implementação de plataforma. Isso resulta no método Dispose do objeto que está sendo invocado, que executa a limpeza necessária.

Para obter mais informações sobre como chamar o método Dispose de um objeto, veja Como usar objetos que implementam IDisposable.