Event Bus e o padrão Observer em C# (.NET): implementação para microsserviços e GUI

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Event Bus e o padrão Observer em C# (.NET): da teoria à implementação



No desenvolvimento moderno em C# (.NET), surge frequentemente a necessidade de organizar a interação entre componentes do sistema, mantendo sua independência. O padrão Observer e sua evolução — Event Bus (Barramento de Eventos) — são ferramentas-chave para implementar o acoplamento fraco (loose coupling). Neste artigo, vamos analisar como esses mecanismos funcionam e criar uma implementação simples, porém funcional, de um Event Bus em C#.



Padrão Observer: abordagem clássica



O padrão Observer define uma relação "um para muitos" entre objetos: quando um objeto (publicador) muda seu estado, todos os objetos dependentes (assinantes) são notificados automaticamente. No .NET, esse padrão é incorporado através de eventos (event) e delegados.



Desvantagens da implementação clássica:

  • Dependência direta do assinante em relação ao publicador (é necessário armazenar uma referência ao objeto).
  • Dificuldade no gerenciamento de assinaturas em sistemas grandes.
  • Problemas com threads (multithreading requer sincronização adicional).


Event Bus: mediador centralizado



O Event Bus resolve esses problemas atuando como um mediador central. Em vez de se inscrever diretamente em um objeto específico, os componentes se registram no barramento de eventos. Os publicadores publicam eventos no barramento, e o barramento os distribui para todos os assinantes. Isso implementa o padrão Pub/Sub (Publish/Subscribe).



Vantagens do Event Bus:

  • Acoplamento fraco: publicadores e assinantes não sabem nada uns sobre os outros.
  • Escalabilidade: fácil adicionar novos assinantes.
  • Versatilidade: adequado para GUI (WPF/WinForms), microsserviços e jogos (Unity).


Implementação de um Event Bus em C# (.NET)



Vamos criar uma implementação básica de um Event Bus que suporte processamento assíncrono e eventos tipados. Para isso, usaremos a interface IEvent e a classe genérica EventBus.



Passo 1: Definir os tipos básicos.

// Interface base para todos os eventospublic interface IEvent { }

// Exemplo de evento - mensagem de usuáriopublic class UserCreatedEvent : IEvent{ public int UserId { get; } public string Email { get; }

public UserCreatedEvent(int userId, string email) { UserId = userId; Email = email; }}


Passo 2: Criar o barramento de eventos.

using System;using System.Collections.Concurrent;using System.Threading.Tasks;

public class EventBus{ // Armazenamento de assinantes: chave - tipo do evento, valor - lista de manipuladores private readonly ConcurrentDictionary<Type, ConcurrentBag<object>> _subscribers = new();

// Assinatura de evento public void Subscribe<TEvent>(Func<TEvent, Task> handler) where TEvent : IEvent { var eventType = typeof(TEvent); var handlers = _subscribers.GetOrAdd(eventType, _ => new ConcurrentBag<object>()); handlers.Add(handler); }

// Cancelamento de assinatura (simplificado - remove todos os manipuladores deste tipo) public void Unsubscribe<TEvent>() where TEvent : IEvent { _subscribers.TryRemove(typeof(TEvent), out _); }

// Publicação de evento (assíncrona) public async Task PublishAsync<TEvent>(TEvent eventData) where TEvent : IEvent { if (!_subscribers.TryGetValue(typeof(TEvent), out var handlers)) return;

foreach (var handler in handlers) { if (handler is Func<TEvent, Task> typedHandler) { await typedHandler(eventData); } } }}


Passo 3: Uso na aplicação.

public class                    

Recommendations