Skip to content

Commit d4aa805

Browse files
committed
Focus on value proposition
1 parent 17bc6db commit d4aa805

File tree

5 files changed

+97
-37
lines changed

5 files changed

+97
-37
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ Define a message and a handler — no interfaces or base classes required:
3434
```csharp
3535
public record Ping(string Text);
3636

37-
public static class PingHandler
37+
public class PingHandler
3838
{
39-
public static string Handle(Ping msg) => $"Pong: {msg.Text}";
39+
public string Handle(Ping msg) => $"Pong: {msg.Text}";
4040
}
4141
```
4242

docs/guide/getting-started.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Getting Started
22

3-
Build a completely message-oriented, loosely coupled app that's easy to test — with near-direct-call performance and zero boilerplate. Get up and running in under a minute.
3+
Most .NET apps start simple and gradually become a tangled web of services calling services. Foundatio Mediator helps you avoid that from day one. Instead of components calling each other directly, every interaction flows through messages — so your code stays loosely coupled, easy to test, and easy to understand as it grows.
4+
5+
You get all of this with near-direct-call performance and zero boilerplate. Get up and running in under a minute.
46

57
## Quick Start
68

@@ -17,9 +19,9 @@ dotnet add package Foundatio.Mediator
1719
public record Ping(string Text);
1820

1921
// Any class ending in "Handler" is discovered automatically
20-
public static class PingHandler
22+
public class PingHandler
2123
{
22-
public static string Handle(Ping msg) => $"Pong: {msg.Text}";
24+
public string Handle(Ping msg) => $"Pong: {msg.Text}";
2325
}
2426
```
2527

@@ -209,13 +211,16 @@ See [Clean Architecture](./clean-architecture) for a complete modular monolith e
209211
| Topic | Description |
210212
| ----- | ----------- |
211213
| [Handler Conventions](./handler-conventions) | All discovery rules, method names, static handlers, explicit attributes |
214+
| [Events & Notifications](./events-and-notifications) | Publish/subscribe, cascading messages, dynamic subscriptions |
215+
| [Authorization](./authorization) | Built-in auth for endpoints and direct mediator calls, policies, roles |
212216
| [Dependency Injection](./dependency-injection) | Lifetimes, parameter injection, constructor vs method injection |
213217
| [Result Types](./result-types) | `Result<T>` API, status codes, validation errors |
214218
| [Middleware](./middleware) | Pipeline hooks, ordering, state passing, short-circuiting |
215219
| [Endpoints](./endpoints) | Route conventions, OpenAPI, authorization, filters |
216220
| [Configuration](./configuration) | All compile-time and runtime options |
217221
| [Streaming Handlers](./streaming-handlers) | `IAsyncEnumerable<T>` support and dynamic subscriptions |
218222
| [Performance](./performance) | Benchmarks and how interceptors work |
223+
| [Clean Architecture](./clean-architecture) | Modular monolith example with cross-assembly handlers |
219224
| [Troubleshooting](./troubleshooting) | Common issues and solutions |
220225

221226
::: info LLM-Friendly Docs

docs/guide/what-is-foundatio-mediator.md

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
# What is Foundatio Mediator?
22

3-
Foundatio Mediator is a high-performance, convention-based mediator pattern implementation for .NET applications. It leverages modern C# features like source generators and interceptors to deliver near-direct call performance while maintaining the benefits of the mediator pattern.
3+
Foundatio Mediator is a convention-based mediator library for .NET that makes it easy to build loosely coupled, maintainable, and testable applications — without sacrificing performance or drowning in boilerplate. It leverages source generators and C# interceptors to deliver near-direct call performance at runtime while giving your team clean architectural boundaries at design time.
44

5-
## What is the Mediator Pattern?
5+
## The Problem: How Codebases Become Unmaintainable
66

7-
The mediator pattern defines how a set of objects interact with each other. Instead of objects communicating directly, they communicate through a central mediator. This promotes loose coupling and makes your code more maintainable and testable.
7+
Every application starts clean. A controller calls a service, the service calls a repository, and everything is easy to follow. But as the application grows, things get tangled:
8+
9+
- **Services call other services**, creating a web of direct dependencies that's hard to trace and harder to change
10+
- **Business logic spreads** across controllers, services, and helpers with no clear boundaries
11+
- **Testing becomes painful** — to test one class, you need to mock a chain of dependencies it was never designed to work without
12+
- **Changes ripple unpredictably** — a small modification in one service breaks three others that depend on it directly
13+
- **New team members struggle** to understand what calls what and where a feature actually lives
14+
15+
This is the **big ball of mud** — and it's the natural outcome when components communicate directly instead of through clear, well-defined boundaries.
16+
17+
## The Mediator Pattern: A Way Out
18+
19+
The mediator pattern solves this by introducing a simple rule: **components never call each other directly**. Instead, they send messages through a central mediator, and handlers pick them up on the other side.
820

921
```mermaid
1022
graph TD
@@ -17,6 +29,16 @@ graph TD
1729
M --> MW[Middleware]
1830
```
1931

32+
This single change has profound effects:
33+
34+
- **Loose coupling** — The sender doesn't know (or care) who handles the message. You can change, replace, or remove handlers without touching callers.
35+
- **Compose with events** — Publish an event like `OrderCreated` and any number of handlers react — sending emails, updating inventory, writing audit logs — without knowing about each other. Add new behavior without modifying existing code.
36+
- **Clear boundaries** — Each handler does one thing. Business logic has an obvious home.
37+
- **Easy testing** — Handlers are self-contained. Test them in isolation with real assertions, not mock verification chains.
38+
- **Safe refactoring** — Rename, split, or reorganize handlers without breaking the rest of the app.
39+
40+
The catch? Traditional mediator libraries make you pay for these benefits with boilerplate interfaces, runtime reflection overhead, and framework lock-in. Foundatio Mediator eliminates those costs.
41+
2042
## Key Benefits
2143

2244
### 🚀 Exceptional Performance
@@ -134,16 +156,28 @@ public class LoggingMiddleware
134156
}
135157
```
136158

159+
## What This Means for Your Team
160+
161+
The features above aren't just technical checkboxes — they translate directly into a healthier codebase and a more productive team:
162+
163+
- **Avoid the big ball of mud** — Message-based communication enforces boundaries that prevent the tight coupling that makes large codebases unmaintainable. Your code stays organized as it grows.
164+
- **Compose logic through events** — When an order is created, the email handler, audit handler, and inventory handler all react independently. None of them know about each other. Need a new reaction? Add a handler — no existing code changes.
165+
- **Ship changes confidently** — When handlers are self-contained and loosely coupled, you can modify one feature without worrying about breaking others. Refactoring goes from scary to routine.
166+
- **Test without fighting the framework** — Handlers are plain classes. Write focused unit tests that assert on real behavior, not mock setups. No mediator fakes, no DI container in tests.
167+
- **Onboard developers faster** — Clear conventions mean new team members learn the pattern once and can navigate the entire codebase. Every feature follows the same structure: message in, handler processes, result out.
168+
- **No performance penalty for good architecture** — Unlike other mediator libraries that add measurable overhead per call, Foundatio Mediator compiles away the indirection. You get a well-structured codebase that runs as fast as hand-wired code.
169+
- **No boilerplate tax** — No marker interfaces, no base classes, no manual DI registration. The source generator handles the wiring so you can focus on business logic.
170+
137171
## When to Use Foundatio Mediator
138172

139173
### ✅ Great For
140174

175+
- **Any app that needs to stay maintainable** as it grows beyond a handful of services
141176
- **Clean Architecture** applications with command/query separation
142177
- **Microservices** with clear request/response boundaries
143178
- **Event-driven** architectures with publish/subscribe patterns
144-
- **High-performance** scenarios where every nanosecond matters
145179
- **Large teams** needing consistent patterns and conventions
146-
- **Testing** scenarios requiring isolated, mockable handlers
180+
- **High-performance** scenarios where mediator overhead is usually accepted as a cost of good architecture
147181

148182
### ⚠️ Consider Alternatives For
149183

docs/guide/why-foundatio-mediator.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,26 @@
11
# Why Choose Foundatio Mediator?
22

3-
Foundatio Mediator stands out from other mediator implementations by combining exceptional performance with developer-friendly conventions. Here's why it might be the right choice for your project.
3+
## The Problem: Complexity That Creeps In
4+
5+
Every .NET application starts clean. But as features accumulate, services start calling other services, dependencies multiply, and before long you have a tightly-coupled codebase that’s hard to test, hard to change, and hard for new team members to navigate. This is the **big ball of mud**, and it’s the default outcome when there’s nothing enforcing boundaries between components.
6+
7+
The mediator pattern solves this: route all interactions through messages instead of direct calls, and your components stay decoupled by design. Need something to happen when an order is created? Publish an `OrderCreated` event — email, audit, and inventory handlers each react independently, without knowing about each other. Adding new behavior means adding a handler, not modifying existing code.
8+
9+
But traditional mediator libraries make you pay for this architecture with boilerplate interfaces, runtime reflection overhead, and framework lock-in.
10+
11+
**Foundatio Mediator gives you the architecture benefits without the costs.**
12+
13+
## What You Actually Get
14+
15+
| Benefit | How |
16+
| ------- | --- |
17+
| **Loose coupling without ceremony** | No interfaces, no base classes — just naming conventions. Components communicate through messages, never directly. |
18+
| **Compose logic through events** | Publish an event and any number of handlers react independently. Add new behavior without touching existing code — the ultimate open/closed principle. |
19+
| **Testability by default** | Handlers are plain classes. Unit test them like any other object — no mediator mocking, no DI container setup. |
20+
| **Maintainability at scale** | Clear command/query/event boundaries prevent your codebase from growing into an unmaintainable mess. Every feature follows the same pattern. |
21+
| **No performance penalty** | Source generators and C# interceptors compile mediator calls into near-direct method calls. The pattern pays for itself. |
22+
| **No boilerplate tax** | The source generator handles all DI registration, dispatch wiring, and endpoint generation. You write business logic, nothing else. |
23+
| **Faster onboarding** | New developers learn the conventions once and can navigate the entire codebase. Message in, handler processes, result out. |
424

525
## Performance That Matters
626

@@ -287,11 +307,11 @@ Compare this to complex reflection-based call stacks in other libraries.
287307

288308
### ✅ Ideal For
289309

290-
- **High-performance applications** where every nanosecond matters
310+
- **Any app that needs to stay maintainable** as it grows — the mediator pattern prevents the big ball of mud
291311
- **Clean architecture** implementations with CQRS patterns
292312
- **Event-driven systems** with publish/subscribe needs
293-
- **Teams preferring conventions** over explicit interfaces
294-
- **Applications requiring robust error handling** without exceptions
313+
- **Teams that value consistency** — conventions mean everyone follows the same patterns
314+
- **High-performance applications** where other mediator libraries add unacceptable overhead
295315
- **Projects wanting excellent testing experience** without framework coupling
296316

297317
### ⚠️ Consider Alternatives When
@@ -336,4 +356,4 @@ Ready to experience the benefits of Foundatio Mediator?
336356
1. [Installation & Setup](./getting-started) - Get running in minutes
337357
2. [Simple Examples](https://github.com/FoundatioFx/Foundatio.Mediator/tree/main/samples) - See the patterns in action
338358

339-
The combination of exceptional performance, developer-friendly conventions, and robust error handling makes Foundatio Mediator an excellent choice for modern .NET applications.
359+
The combination of loose coupling, testability, maintainability, and exceptional performance — without the usual boilerplate tax — makes Foundatio Mediator an excellent choice for modern .NET applications.

docs/index.md

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ layout: home
33

44
hero:
55
name: Foundatio Mediator
6-
text: Blazingly Fast C# Mediator
7-
tagline: Convention-based mediator powered by source generators and interceptors
6+
text: Build Loosely Coupled .NET Apps — Without the Tradeoffs
7+
tagline: Easy to maintain, easy to test, and blazingly fast — a convention-based mediator powered by source generators and interceptors
88
image:
99
src: https://raw.githubusercontent.com/FoundatioFx/Foundatio/main/media/foundatio-icon.png
1010
alt: Foundatio Mediator
@@ -17,21 +17,29 @@ hero:
1717
link: https://github.com/FoundatioFx/Foundatio.Mediator
1818

1919
features:
20+
- icon: 🧩
21+
title: Loosely Coupled by Default
22+
details: Every interaction flows through messages, so components never call each other directly. Change, replace, or remove any handler without ripple effects across your codebase.
23+
link: /guide/what-is-foundatio-mediator
24+
- icon: 🔗
25+
title: Compose with Events
26+
details: Publish an event and any number of handlers react — without knowing about each other. Add new behavior to your app without modifying existing code.
27+
link: /guide/events-and-notifications
28+
- icon: 🧪
29+
title: Easy to Test
30+
details: Handlers are plain classes with no framework base types. Unit test them like any other object — no mediator mocking, no DI container, no ceremony.
31+
link: /guide/testing
2032
- icon:
21-
title: Near-Direct Call Performance
22-
details: Zero runtime reflection with source generators and C# interceptors for blazing fast execution.
33+
title: No Performance Tax
34+
details: Source generators and C# interceptors compile your mediator calls into near-direct method calls. You get the architecture benefits without the runtime overhead.
2335
link: /guide/performance
2436
- icon: 🎯
25-
title: Convention-Based Discovery
26-
details: No interfaces or base classes required. Just name your classes and methods following simple conventions.
27-
link: /guide/handler-conventions
28-
- icon: 🧩
29-
title: Plain Handler Classes
30-
details: Use regular classes or static methods. Sync or async, any signature, multiple handlers per class. No framework coupling.
37+
title: Convention-Based, Zero Boilerplate
38+
details: No interfaces, no base classes, no manual registration. Just name your classes and methods following simple conventions — the source generator handles all the wiring.
3139
link: /guide/handler-conventions
3240
- icon: 🌐
3341
title: Auto-Generated API Endpoints
34-
details: Full Minimal API endpoints generated from your handlers — routes, methods, parameter binding, OpenAPI metadata, and authorization all inferred automatically. No boilerplate.
42+
details: Full Minimal API endpoints generated from your handlers — routes, methods, parameter binding, OpenAPI metadata, and authorization all inferred automatically.
3543
link: /guide/endpoints
3644
- icon: 📡
3745
title: Real-Time Streaming
@@ -54,15 +62,8 @@ features:
5462
details: Return tuples to automatically publish additional messages in sequence — ideal for event-driven workflows.
5563
link: /guide/cascading-messages
5664
- icon: 🔒
57-
title: Compile-Time Safety
58-
details: Comprehensive compile-time diagnostics and validation to catch errors early.
59-
link: /guide/troubleshooting
60-
- icon: 🧪
61-
title: Easy Testing
62-
details: Handlers are plain objects, making unit testing straightforward without framework mocking.
63-
- icon: 🐛
64-
title: Superior Debugging
65-
details: Short, simple call stacks with minimal indirection for excellent debugging experience.
65+
title: Compile-Time Safety & Debugging
66+
details: Comprehensive diagnostics catch errors early. Short, simple call stacks with minimal indirection make debugging straightforward.
6667
---
6768

6869
## Quick Example
@@ -72,9 +73,9 @@ Create a simple handler by following naming conventions:
7273
```csharp
7374
public record Ping(string Text);
7475

75-
public static class PingHandler
76+
public class PingHandler
7677
{
77-
public static string Handle(Ping msg) => $"Pong: {msg.Text}";
78+
public string Handle(Ping msg) => $"Pong: {msg.Text}";
7879
}
7980
```
8081

0 commit comments

Comments
 (0)