Skip to content

FoundatioFx/Foundatio.Mediator

Repository files navigation

FoundatioFoundatio

Build status NuGet Version feedz.io Discord

Blazingly fast, convention-based C# mediator powered by source generators and interceptors.

✨ Why Choose Foundatio Mediator?

  • 🚀 Near-direct call performance - Zero runtime reflection, minimal overhead
  • Convention-based - No interfaces or base classes required
  • 🔧 Full DI support - Microsoft.Extensions.DependencyInjection integration
  • 🧩 Plain handler classes - Drop in static or instance methods anywhere
  • 🎪 Middleware pipeline - Before/After/Finally hooks with state passing
  • 🎯 Built-in Result<T> - Rich status handling without exceptions
  • 🔄 Tuple returns - Automatic cascading messages
  • 🔒 Compile-time safety - Early validation and diagnostics
  • 🧪 Easy testing - Plain objects, no framework coupling
  • 🐛 Superior debugging - Short, simple call stacks

🚀 Complete Example

1. Install & Register

dotnet add package Foundatio.Mediator
// Program.cs
services.AddMediator();

2. Create Messages & Handlers

// Messages (records, classes, anything)
public record GetUser(int Id);
public record CreateUser(string Name, string Email);
public record UserCreated(int UserId, string Email);

// Handlers - just plain classes ending with "Handler" or "Consumer"
public class UserHandler
{
    public async Task<Result<User>> HandleAsync(GetUser query, IUserRepository repo)
    {
        var user = await repo.FindAsync(query.Id);
        return user ?? Result.NotFound($"User {query.Id} not found");
    }

    public async Task<(User user, UserCreated evt)> HandleAsync(CreateUser cmd, IUserRepository repo)
    {
        var user = new User { Name = cmd.Name, Email = cmd.Email };
        await repo.AddAsync(user);

        // Return tuple: first element is response, rest are auto-published
        return (user, new UserCreated(user.Id, user.Email));
    }
}

// Event handlers
public class EmailHandler
{
    public async Task HandleAsync(UserCreated evt, IEmailService email)
    {
        await email.SendWelcomeAsync(evt.Email);
    }
}

// Middleware - classes ending with "Middleware"
public class LoggingMiddleware(ILogger<LoggingMiddleware> logger)
{
    public Stopwatch Before(object message) => Stopwatch.StartNew();

    public void Finally(object message, Stopwatch sw, Exception? ex)
    {
        logger.LogInformation("Handled {MessageType} in {Ms}ms",
            message.GetType().Name, sw.ElapsedMilliseconds);
    }
}

3. Use the Mediator

// Query with response
var result = await mediator.InvokeAsync<Result<User>>(new GetUser(123));
if (result.IsSuccess)
    Console.WriteLine($"Found user: {result.Value.Name}");

// Command with automatic event publishing
var user = await mediator.InvokeAsync<User>(new CreateUser("John", "john@example.com"));
// UserCreated event automatically published to EmailHandler

// Publish events to multiple handlers
await mediator.PublishAsync(new UserCreated(user.Id, user.Email));

📚 Learn More

👉 Complete Documentation

Key topics:

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request. See our documentation for development guidelines.

📄 License

MIT License

About

Blazingly fast, convention-based C# mediator powered by source generators and interceptors.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors 3

  •  
  •  
  •  

Languages