Injeção de dependência

A injeção de dependência no ModularBr: como funciona e seus benefícios.

A injeção de dependência é um padrão de projeto comum em desenvolvimento de software que tem como objetivo reduzir o acoplamento entre os componentes da aplicação e facilitar a manutenção do código. No ModularBr, esse padrão é amplamente utilizado para gerenciar as dependências entre os módulos.

A injeção de dependência no ModularBr funciona da seguinte forma: os módulos definem suas dependências e o InjectorBr se encarrega de resolver as dependências e instanciar os objetos necessários em tempo de execução. Isso permite que os módulos sejam desenvolvidos de forma independente e que a aplicação possa ser facilmente modificada sem afetar outros módulos.

Além disso, a injeção de dependência no ModularBr traz outros benefícios, como a possibilidade de testar os módulos de forma isolada e a melhoria da legibilidade e manutenção do código. Com a separação clara das responsabilidades e das dependências entre os módulos, é mais fácil entender como a aplicação funciona e realizar modificações ou correções sem impactar outras partes do sistema.

Em resumo, a injeção de dependência é um recurso fundamental no ModularBr que contribui para a modularidade, flexibilidade e manutenibilidade do código. Com ela, é possível criar aplicações mais robustas, escaláveis e fáceis de manter.

Registro de instância

A estratégia para construir uma instância com suas dependências consiste em registrar todos os objetos em um módulo e fabricando-os sob demanda ou em forma de instância única (singleton). Esse 'registro' é chamado de Bind.

Criando um Bind para registrar instâncias:

  • Bind<>.Singleton: Cria uma instância apenas uma vez quando o módulo é iniciado.

  • Bind<>.SingletonLazy: Crie uma instância apenas uma vez quando solicitado.

  • Bind<>.Factory: Cria uma instância sob demanda.

  • Bind<>.SingletonInterface: Cria Interface singletton sobe demanda do método .GetInterface<TClass>.

  • Bind<>.Instance: Adiciona uma instância existente.

Exemplo de uso:

unit nfe.module;

interface

uses
  dmfbr.module,
  nfe.repository, nfe.provider, nfe.controller;

type
  TNFeModule = class(TModule)
  public
    function Routes: TRoutes; override;
    function Binds: TBinds; override;
  end;

implementation

{ TNFeModule }

function TNFeModule.Binds: TBinds;
begin
  // Injeção de dependência
  Result := [Bind<TRepositoryServer>.SingletonLazy,
             Bind<TControllerServer>.Singleton,
             Bind<TProviderORMBr>.Factory];
end;

function TNFeModule.Routes: TRoutes;
begin
  Result := [RouteModule('/nfe/v1/pdf/:key', TPDFModulo),
             RouteModule('/nfe/v1/xml/:key', TXMLModulo)];
end;

end.

ATENÇÃO

Para que uma vinculação seja elegível para substituição, a vinculação DEVE ter o tipo declarado no construtor Bind. (ex: Bind<TMyObjectType>() );

Parâmetros no Construtor

Singleton<T> - SingletonLazy<T> - SingletonInterface<I> e Factory<T>, tem os seguintes parâmetros:

  1. Parâmetro AOnCreate

  2. Parâmetro AOnDestroy

  3. Parâmetro AOnConstructorParams

OnCreate

O parâmetro AOnCreate é um parâmetro opcional do métodos. Ele é usado para especificar um procedimento que deve ser executado quando uma nova instância da classe T é criada pelo contêiner de injeção de dependência.

Ele é uma procedure anônima que pode ser passado como parâmetro. O procedimento deve ter um parâmetro de entrada do tipo T, que é a instância recém-criada da classe T. O AOnCreate é opcional e pode ser usado para executar qualquer código adicional que seja necessário para configurar a instância antes que ela seja usada.

Por exemplo, se uma classe T tiver uma propriedade que precisa ser configurada com um valor específico antes que ela possa ser usada, você pode definir um procedimento que execute essa configuração e, em seguida, passá-lo como o parâmetro AOnCreate ao criar uma nova instância da classe T.

InjectorBr.Factory<TMasterClass>(
  procedure (Value: TMasterClass)
  begin
    Value.IncludeChild(InjectorBr.Get<TChildClass>);
    Value.ValueInicial := true;
  end);

OnDestroy

O parâmetro AOnDestroy é um parâmetro opcional do métodos. Ele é usado para especificar um procedimento que deve ser executado quando uma instância da classe T é destruída pelo contêiner de injeção de dependência.

Ele é uma procedure anônimo que pode ser passado como parâmetro. O procedimento deve ter um parâmetro de entrada do tipo T, que é a instância que está sendo destruída. O AOnDestroy é opcional e pode ser usado para executar qualquer código adicional que seja necessário antes que a instância seja destruída.

Por exemplo, se uma classe T tiver um recurso externo que precise ser liberado antes que a instância seja destruída, você pode definir um procedimento que libere o recurso e, em seguida, passá-lo como o parâmetro AOnDestroy ao criar uma nova instância da classe T.

InjectorBr.Factory<TMasterClass>(
  procedure (Value: TMasterClass)
  begin
    ShowMessage('Destroy: ' + Value.ClassName);
  end);

OnConstructorParams

O parâmetro AOnConstructorParams é um parâmetro opcional dos métodos. Ele é usado para permitir que você injete parâmetros em um construtor de classe genérica quando a instância é criada pelo contêiner de injeção de dependência.

O tipo de AOnConstructorParams é TConstructorCallback, que é um tipo de função que você deve definir e passar como parâmetro. A função TConstructorCallback retorna um array de TValues. Esse array representa os parâmetros que serão injetados no construtor da classe genérica.

Ao usar AOnConstructorParams, você pode personalizar a criação de uma instância de classe genérica para atender às suas necessidades específicas. Por exemplo, se uma classe genérica tiver um construtor que aceite parâmetros, você pode usar AOnConstructorParams para passar esses parâmetros ao criar uma instância da classe genérica. Isso pode ser especialmente útil se você precisar injetar dependências adicionais em uma classe genérica que não podem ser resolvidas pelo contêiner de injeção de dependência sozinho.

InjectorBr.Factory<TMasterClass>(nil, nil,
  function: TConstructorParams
  begin
    Result := [TValue.From<TChildClass>(InjectorBr.Get<TChildClass>)];
  end);

IMPORTANTE Por que OnConstructorParams é opcional ? Porque no ModularBr, o Injector é responsável por tratar a injeção de parâmetros no construtor das classes. Ele tem a capacidade de buscar as dependências necessárias e injetá-las automaticamente no momento da criação da instância da classe.

Quando você define uma classe com um construtor que possui parâmetros, o Injector do ModularBr analisa esses parâmetros e verifica quais são as dependências necessárias. Em seguida, ele busca essas dependências dentro do próprio contexto do ModularBr e as injeta no construtor da classe.

Isso significa que você não precisa se preocupar em criar manualmente as instâncias das dependências e passá-las para o construtor. O Injector faz todo esse trabalho de forma automática, tornando o processo de injeção de dependência mais conveniente e eficiente.

Essa abordagem do Injector no ModularBr simplifica o desenvolvimento, pois você pode se concentrar na lógica da classe sem se preocupar com a criação e gerenciamento das dependências. O ModularBr cuida disso para você, garantindo que as dependências sejam resolvidas e injetadas corretamente.

Last updated