Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Orbis25/FoundationKit/llms.txt
Use this file to discover all available pages before exploring further.
FoundationKit.Events provides a lightweight, convention-driven event bus on top of RabbitMQ. A single AddEvents call wires up the connection, declares the exchange, registers the IRabbitMessageBroker publisher, scans all loaded assemblies for IMessageHandler<T> implementations, and starts a background RabbitMqConsumerService that dispatches incoming messages to the right handler automatically — no manual consumer registration needed.
Setup
Add theFoundationKit.Events NuGet package to your project, then call AddEvents in Program.cs with a configured RabbitConfig:
RabbitConfig fields:
| Property | Type | Default | Description |
|---|---|---|---|
Url | string? | null | Full AMQP connection string (e.g. amqp://user:pass@host:5672). Takes priority over individual fields. |
User | string? | "guest" | RabbitMQ username (used when Url is not set) |
Password | string? | "guest" | RabbitMQ password |
Host | string? | "localhost" | RabbitMQ hostname |
Port | int | AMQP default | RabbitMQ port (5672) |
DefaultExchange | string | (required) | Exchange name where all messages are published |
DefaultExchangeType | ExchangeType | Topic | Exchange type: Topic, Fanout, Direct, or Headers |
QueuePrefix | string | (required) | Prefixed to every queue name: {QueuePrefix}:{MessageTypeName} |
RedeliverUnackedMessages | bool | true | If true, nacks unprocessed messages back to the queue for redelivery |
Url is provided it is used exclusively. When it is null, the library connects using Host, Port, User, and Password.
Defining a message
A message is any class that implements the marker interfaceIMessage. No base class or extra properties are required:
EventMessage<T> envelope that carries metadata:
Publishing
InjectIRabbitMessageBroker and call PublishAsync. Both a single-message and a batch overload are available:
Subscribing
Tell FoundationKit which message types need a queue by callingAddSubscriber<T>() after AddEvents. A queue named {QueuePrefix}:{TypeName} is declared and bound to the default exchange with a routing key matching the type name:
exchange argument to bind to a different exchange:
Consuming
ImplementIMessageHandler<TMessage> to process incoming messages. The interface declares a single method:
IMessageHandler<T> implementations across loaded assemblies and invokes them when a matching message arrives:
IMessageHandler<T> implementations are discovered automatically at startup across all assemblies loaded into the current AppDomain, including referenced libraries. You do not need to register them manually — AddEvents calls RegisterConsumers internally, which scans assemblies and registers every handler with AddScoped.How it works
RabbitMqConsumerService runs as an IHostedService (BackgroundService) for the lifetime of the application:
Channel setup
Creates a new
IChannel on startup and sets QoS to prefetch 10 messages (BasicQosAsync(0, 10, false)).Queue and binding declaration
For every
QueueDefinition registered by AddSubscriber<T>(), the service calls QueueDeclareAsync (durable, non-exclusive, no auto-delete) and QueueBindAsync to link the queue to the exchange with the routing key.Message dispatch
On
ReceivedAsync, deserialises the body as EventMessage<T> (the type is read from BasicProperties.Type), creates a DI scope, resolves the matching IMessageHandler<T>, and calls HandleAsync.