Event Bus y el patrón Observer en C# (.NET): implementación para microservicios y GUI

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Event Bus y el patrón Observer en C# (.NET): de la teoría a la implementación



En el desarrollo moderno con C# (.NET), a menudo surge la necesidad de organizar la interacción entre componentes del sistema, manteniendo su independencia. El patrón Observer y su evolución — Event Bus (Bus de eventos) — son herramientas clave para implementar el acoplamiento débil (loose coupling). En este artículo, analizaremos cómo funcionan estos mecanismos y crearemos una implementación simple pero funcional de un Event Bus en C#.



Patrón Observer: el enfoque clásico



El patrón Observer define una relación de "uno a muchos" entre objetos: cuando un objeto (publicador) cambia su estado, todos los objetos dependientes (suscriptores) son notificados automáticamente. En .NET, este patrón está integrado a través de eventos (event) y delegados.



Desventajas de la implementación clásica:

  • Dependencia directa del suscriptor respecto al publicador (es necesario almacenar una referencia al objeto).
  • Complejidad en la gestión de suscripciones en sistemas grandes.
  • Problemas con hilos (la concurrencia requiere sincronización adicional).


Event Bus: mediador centralizado



Event Bus resuelve estos problemas actuando como un mediador central. En lugar de suscribirse directamente a un objeto específico, los componentes se registran en el bus de eventos. Los publicadores publican eventos en el bus, y el bus los distribuye a todos los suscriptores. Esto implementa el patrón Pub/Sub (Publish/Subscribe).



Ventajas de Event Bus:

  • Acoplamiento débil: los publicadores y suscriptores no saben nada el uno del otro.
  • Escalabilidad: es fácil agregar nuevos suscriptores.
  • Versatilidad: adecuado para GUI (WPF/WinForms), microservicios y juegos (Unity).


Implementación de Event Bus en C# (.NET)



Crearemos una implementación básica de Event Bus que soporte procesamiento asíncrono y eventos tipados. Para ello, utilizaremos la interfaz IEvent y la clase genérica EventBus.



Paso 1: Definir los tipos base.

// Interfaz base para todos los eventospublic interface IEvent { }

// Ejemplo de evento - mensaje de usuariopublic class UserCreatedEvent : IEvent{ public int UserId { get; } public string Email { get; }

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


Paso 2: Crear el bus de eventos.

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

public class EventBus{ // Almacenamiento de suscriptores: clave - tipo de evento, valor - lista de manejadores private readonly ConcurrentDictionary<Type, ConcurrentBag<object>> _subscribers = new();

// Suscripción a un 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); }

// Cancelar suscripción (simplificada - elimina todos los manejadores de este tipo) public void Unsubscribe<TEvent>() where TEvent : IEvent { _subscribers.TryRemove(typeof(TEvent), out _); }

// Publicación de evento (así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); } } }}


Paso 3: Uso en la aplicación.

public class                    

Recommendations