Árvore de páginas

No C# uma classe pode definir comportamentos a serem disparados quando determinada ação acontece. Esses comportamentos podem ser assinados para que quando ocorram alguém seja notificado.

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.

No TNF encontramos suporte ao um pattern chamado Domain Event.

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

EventBus

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

Criando um evento e definindo seu comportamento

Abaixo tomamos como exemplo a criação de um evento para o registro da entidade Person.

NewRegistrationHandler
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 (injeção de dependência através de convenções) 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 disparado.

Disparando Eventos

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

RegistrationService.cs
using Tnf.Architecture.Domain.Events;
using Tnf.Architecture.Domain.Interfaces.Services;
using Tnf.App.Domain.Services;
using Tnf.Dto;
using Tnf.Events.Bus;

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

        public PersonDto Register(PersonDto dto)
        {
            var builder = new PersonBuilder()
                   .WithName(dto.Name);
 
            var person = builder.Build();
            if (!Notification.HasNotification())
            {
                var id = Repository.CreatePerson(person);
                dto.Id = id;
            }

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

Observe que após o objeto de domínio ser construído e estar valido, 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.

  • Sem rótulos