Skip to content
mobius1qwe edited this page Nov 13, 2026 · 1 revision

Home > Serviços (contêiner de dependências) 🚧

Serviços: o contêiner de dependências

Important

Em desenvolvimento (2.0). Ainda não está numa versão lançada e pode mudar.

Vale para a 2.0 · Delphi XE em diante e Lazarus/FPC 3.2 em diante · Nível: intermediário

Em uma frase: o TRALServiceContainer guarda, no Object Inspector, qual classe faz cada serviço da aplicação (o envio de e-mail, o repositório de clientes) e quanto tempo cada instância vive; o handler da rota pede o serviço ao contêiner em vez de criar e liberar objetos à mão.

Você vai precisar: o pacote RALHostingContainerPackage (só requer PascalRAL).

Os serviços

type
  IMailer = interface
    ['{0B2F6A51-3C4D-4E7F-8A9B-1C2D3E4F5A6B}']
    procedure Send(const ATo, AText: string);
  end;

  TMailer = class(TRALService, IMailer)
  public
    procedure Send(const ATo, AText: string);
  end;

initialization
  RALRegisterService(TMailer);    // o contêiner acha a classe pelo nome
  • Uma classe de serviço descende de TRALService (contada por referência, use pela interface) ou de TComponent. O construtor de TRALService recebe o contêiner e o pedido, e pode pedir os serviços de que depende.
  • RALRegisterService torna a classe conhecida pelo nome; quem não quer registrar cria a instância no evento OnCreate do item (ou OnCreateService do contêiner).

No Object Inspector, em Services, um item por serviço:

propriedade o que é
Name o nome pelo qual o serviço é pedido (mailer)
ServiceClass a classe registrada (TMailer)
InterfaceGUID a interface pela qual ele também é pedido
Lifetime slSingleton (uma só, a primeira vez que é pedida), slPerRequest (uma por pedido HTTP, liberada no fim dele) ou slTransient (nova a cada vez)

Pedindo um serviço

procedure TForm1.RotaPedido(ARequest: TRALRequest; AResponse: TRALResponse);
var
  vMailer: IMailer;
begin
  Servicos.Resolve(IMailer, vMailer, ARequest);       // pela interface
  // ou: vMailer := Servicos.Resolve('mailer', ARequest) as IMailer;
  // ou, com genéricos: vMailer := Servicos.ResolveAs<IMailer>(ARequest);
  vMailer.Send('cliente@exemplo.com', 'Pedido recebido');
end;
  • Passe o ARequest do handler: um serviço slPerRequest é o mesmo em todo o pedido (no handler e nos serviços que dependem dele) e é liberado quando o servidor termina o pedido. Pedido fora de um pedido HTTP, ele dá erro.
  • Um singleton é criado uma única vez mesmo com várias threads pedindo ao mesmo tempo, e é liberado com o contêiner (ou em Reset).
  • Um serviço que não é TRALService (um TComponent) é pedido com ResolveObject: singleton e por pedido são do contêiner; um transiente é de quem pediu, que libera.
  • Serviços que se pedem em círculo dão erro em vez de travar o programa.

[Inject] (Delphi 2010 em diante)

Onde o compilador tem atributos e RTTI estendida, ponha RALServiceInject no uses e marque os campos:

uses RALServiceContainer, RALServiceInject;

type
  TPedidos = class(TRALService, IPedidos)
  private
    [Inject] FMailer: IMailer;             // pela interface do campo
    [Inject('clientes')] FClientes: IRepositorio;
  ...

Os campos são preenchidos logo depois do construtor: use-os nos métodos, não no construtor. No Lazarus/FPC 3.2 a unit fica vazia; o construtor pede ao contêiner.

Erros comuns

sintoma causa o que fazer
"A classe ... não está registrada" falta RALRegisterService registre na initialization da unit da classe
"vive por pedido e foi pedido fora de um" slPerRequest sem o ARequest passe o pedido do handler, ou mude o Lifetime
"não tem interface: use ResolveObject" Resolve de um TComponent ResolveObject
o objeto some logo depois de pedido TRALService guardado só como objeto guarde a interface

Veja também

Começar

Servidor

MQTT 🚧

E-mail 🚧

Chatbot 🚧

Cliente

Motores

Avançado

Ajuda

🚧 = em desenvolvimento, pode mudar

Clone this wiki locally