Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

Índice

Visão Geral

No C# uma classe pode definir comportamentos a serem disparados quando determinada ação acontece e outras classes podem registrá-los para ser notificados quando isso acontecer.. Esses comportamentos podem ser assinados para que quando ocorram alguém seja notificado.

O TNF contém suporte ao um pattern chamado Domain Event.

Para usar a estrutura de Domain Events instale o pacote Tnf via nuget disponível em: https://www.myget.org/F/tnf/api/v3/index.json

Eventos ocorrem de forma assíncrona não interrompendo o fluxo normal de seu código dando mais flexibilidade distribuindo-as melhor quando não existe a necessidade de esperar que um processo seja finalizado.

Podemos tomar como um exemplo para este caso o cadastro de um usuário em um sistema: ao cadastrar o usuário podemos criar um evento para notificar a criação do usuário e neste fazer o envio de um e-mail de boas vindas.

Não precisamos esperar o envio do e-mail para que o cadastro seja finalizado. Neste caso o envio do e-mail é um processo secundário que pode ser implementado através do um evento de domínio.Os eventos de domínio podem ser usados para desacoplar a lógica de negócio reagindo a processos ou fluxos de negócio como por exemplo o envio de email a um cliente após o seu cadastro.

EventBus

EventBus é um objeto registrado como singleton no TNF que é compartilhado na aplicação para que seja usado para manipular e controlar os eventos.

EventHandler e EventData

Criando um evento e definindo seu comportamento

Abaixo tomamos como exemplo a criação de um evento para o registro da entidade PersonPara utilizar o EventBus é necessário fazer a injeção da dependência na classe onde o evento precisa ser disparado e fazer a implementação que irá conter a logica de execução deste evento (Handler).

Bloco de código
languagec#
firstline1
titleNewRegistrationHandler
linenumberstrue
using Castle.Core.Logging;
using Tnf.Architecture.Domain.Interfaces.Services;
using Tnf.Dependency;
using Tnf.Events.Bus;
using Tnf.Events.Bus.Handlers;

namespace Tnf.Architecture.Domain.Events
{
    public class NewRegistrationHandler : IEventHandler<NewRegistrationEventData>, ITransientDependency
    {
        private readonly ILogger _logger;

        public NewRegistrationHandler(ILogger logger) => _logger = logger;

        public void HandleEvent(NewRegistrationEventData eventData)
        {
            _logger.Info("Registration event triggered");
        }
    }

    public class NewRegistrationEventData : EventData
    {
        public PersonDto Person { get; }

        public NewRegistrationEventData(PersonDto person)
        {
            Person = person;
        }
    }
}

A primeira classe chamada NewRegistrationHandler contém a implementação do comportamento do evento. Toda vez que o evento for disparado essa classe será chamada. Desta forma observe que a interface ITransientDependency está presente por este motivo. Esse evento é transitório e será criado para cada cadastro criado no sistema.

Perceba que também implementamos o nosso EventData, onde definimos a estrutura de dados do evento disparadoO exemplo acima define a criação da estrutura do Evento (classe NewRegistrationEventData) e o Handler que irá ser disparado (NewRegistrationHandler).

Trigger Events

Na classe abaixo o evento é disparado dentro do serviço de domínio onde é feita a injeção do EventBus:

Bloco de código
languagec#
firstline1
titleRegistrationService.cs
linenumberstrue
using Tnf.Architecture.Domain.Events;
using Tnf.Architecture.Domain.Interfaces.Services;
using Tnf.Domain.Services;
using Tnf.Dto;
using Tnf.Events.Bus;

namespace Tnf.Architecture.Domain.Registration
{
    public class RegistrationService : DomainService<IPersonRepository>, IRegistrationService
    {
        private readonly IEventBus _eventBus;
        public RegistrationService(IPersonRepository repository, IEventBus eventBus)
            : base(repository)
        {
            _eventBus = eventBus;
        }

        public DtoResponseBase<PersonDto> Register(PersonDto dto)
        {
            var response = new DtoResponseBase<PersonDto>();
            var builder = new PersonBuilder()
                   .WithName(dto.Name);

            var build = builder.Build();
            if (!build.Success)
            {
                response.AddNotifications(build.Notifications);
                return response;
            }

            var id = Repository.CreatePerson(dto);
            dto.Id = id;

            // Trigger event before create person
            _eventBus.Trigger(new NewRegistrationEventData(dto));
            return response;
        }
    }
}

 

A estrutura de EventBus está contida no pacote: Tnf

...

Observe que após o objeto de domínio ser construído e passar por todas as validações, o repositório é consumido cadastrando um novo dado, fazendo o disparo do evento através da interface IEventBus injetada em nosso serviço de domínio.

O método Trigger da interface IEventBus recebe o dado do evento representando a sua estrutura. Nesse momento o Handler implementado anteriormente será chamado e executado.