Alveus.EventBus (1.1.0)
Installation
dotnet nuget add source --name public --username your_username --password your_token
dotnet add package --source public --version 1.1.0 Alveus.EventBus
About this package
Provides a decoupled event bus for in-process communication.
Alveus.EventBus
Alveus.EventBus is a lightweight, in-process library for enabling decoupled communication between different parts of an application using a publish-subscribe pattern. This promotes cleaner, more maintainable code by allowing components to interact without having direct dependencies on each other.
This repository contains two packages:
Alveus.EventBus
: The core interfaces.Alveus.EventBus.Memory
: A simple, thread-safe in-memory implementation.
Features
- Simple API: Easy to subscribe to and publish events.
- Decoupled Components: Publishers and subscribers don't need to know about each other.
- Multiple Handler Types: Supports synchronous (
Action<T>
), asynchronous (Func<T, Task>
), and cancellable (Func<T, CancellationToken, Task>
) handlers. - Thread-Safe: The
MemoryEventBus
implementation is thread-safe for concurrent access.
Basic Usage
Here’s a complete example demonstrating how to define, subscribe to, and publish events.
1. Define an Event
An event can be any plain C# class (POCO) that holds the data you want to pass.
// Define an event that will be published when a user logs in.
public class UserLoggedInEvent
{
public string Username { get; }
public DateTime LoginTime { get; }
public UserLoggedInEvent(string username, DateTime loginTime)
{
Username = username;
LoginTime = loginTime;
}
}
2. Create Event Handlers
Handlers are methods that will be executed when an event is published. You can create both synchronous and asynchronous handlers.
// A synchronous handler that logs the event to the console.
public void OnUserLoggedIn(UserLoggedInEvent @event)
{
Console.WriteLine($"[Sync Handler] User '{@event.Username}' logged in at {@event.LoginTime:HH:mm:ss}.");
}
// An asynchronous handler that might perform a longer-running task, like sending an email.
public async Task OnUserLoggedInAsync(UserLoggedInEvent @event)
{
Console.WriteLine($"[Async Handler] Welcome email process for '{@event.Username}' started...");
await Task.Delay(1000); // Simulate sending an email
Console.WriteLine($"[Async Handler] Welcome email for '{@event.Username}' sent.");
}
// A cancellable asynchronous handler that supports cancellation.
public async Task OnUserLoggedInWithCancellationAsync(UserLoggedInEvent @event, CancellationToken cancellationToken)
{
Console.WriteLine($"[Cancellable Handler] Processing login for '{@event.Username}'...");
await Task.Delay(1000, cancellationToken); // Cancellable operation
Console.WriteLine($"[Cancellable Handler] Login processed for '{@event.Username}'.");
}
3. Subscribe and Publish
using Alveus.EventBus;
using Alveus.EventBus.Memory;
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task Main(string[] args)
{
// 1. Create an instance of the event bus.
// IEventBus is often registered as a singleton in a DI container.
IEventBus eventBus = new MemoryEventBus();
// Create an instance of our class containing the handlers
var handlers = new MyEventHandlers();
// 2. Subscribe the handlers.
eventBus.Subscribe<UserLoggedInEvent>(handlers.OnUserLoggedIn);
eventBus.Subscribe<UserLoggedInEvent>(handlers.OnUserLoggedInAsync);
eventBus.Subscribe<UserLoggedInEvent>(handlers.OnUserLoggedInWithCancellationAsync);
// 3. Create an instance of the event.
var loginEvent = new UserLoggedInEvent("Alice", DateTime.UtcNow);
// 4. Publish the event asynchronously.
// PublishAsync will invoke both sync and async handlers and await the async ones.
Console.WriteLine("Publishing UserLoggedInEvent...");
await eventBus.PublishAsync(loginEvent);
Console.WriteLine("All handlers have completed.");
}
}
public class MyEventHandlers
{
// A synchronous handler.
public void OnUserLoggedIn(UserLoggedInEvent @event)
{
Console.WriteLine($"[Sync Handler] User '{@event.Username}' logged in at {@event.LoginTime:HH:mm:ss}.");
}
// An asynchronous handler.
public async Task OnUserLoggedInAsync(UserLoggedInEvent @event)
{
Console.WriteLine($"[Async Handler] Welcome email process for '{@event.Username}' started...");
await Task.Delay(1000); // Simulate sending an email.
Console.WriteLine($"[Async Handler] Welcome email for '{@event.Username}' sent.");
}
}
Output of the Example:
Publishing UserLoggedInEvent...
[Sync Handler] User 'Alice' logged in at 14:30:00.
[Async Handler] Welcome email process for 'Alice' started...
[Async Handler] Welcome email for 'Alice' sent.
All handlers have completed.
Note
When publishing events synchronously with Alveus.EventBus.Memory
using void Publish<TEventType>(TEventType @event)
,
asynchronous handlers will not be called. This is to prevent the situation where handlers get called either as Fire or Forget,
or in a way that blocks execution, introducing the risk of deadlocks.
License
This project is licensed under the MIT License. See the LICENSE.md file for details.