Shows how to compose event handlers in the processing pipelines to:
- filter events,
- transform them,
- NOT requiring marker interfaces for events,
- NOT requiring marker interfaces for handlers,
- enables composition through regular functions,
- allows using interfaces and classes if you want to,
- can be used with Dependency Injection, but also without through builder,
- integrates with MediatR if you want to.
- 📝 Read more How to build a simple event pipeline
Having UserAdded event:
public record UserAdded(
string FirstName,
string LastName,
bool IsAdmin
);
We may want to create a pipeline, that will at first filter admin users:
public static bool IsAdmin(UserAdded @event) =>
@event.IsAdmin;
Then map events to a dedicated AdminAdded
event:
public record AdminAdded(
string FirstName,
string LastName
);
public static AdminAdded ToAdminAdded(UserAdded @event) =>
new(@event.FirstName, @event.LastName);
Then handle mapped events storing information about new admins:
public static void Handle(AdminAdded @event) =>
GlobalAdmins.Add(@event);
And distribute global admins to all tenants:
public static List<AdminGrantedInTenant> SendToTenants(UserAdded @event) =>
TenantNames
.Select(tenantName =>
new AdminGrantedInTenant(@event.FirstName, @event.LastName, tenantName)
)
.ToList();
public record AdminGrantedInTenant(
string FirstName,
string LastName,
string TenantName
);
public static void Handle(AdminGrantedInTenant @event) =>
AdminsInTenants.Add(@event);
}
MediatR is great, but it doesn't enable such advanced pipelines. This sample shows how to construct event pipelines seamlessly. See EventBus implementation.
You can use it with Dependency Injection
serviceCollection
.AddEventBus()
.Filter<UserAdded>(AdminPipeline.IsAdmin)
.Transform<UserAdded, AdminAdded>(AdminPipeline.ToAdminAdded)
.Handle<AdminAdded>(AdminPipeline.Handle)
.Transform<UserAdded, List<AdminGrantedInTenant>>(AdminPipeline.SendToTenants)
.Handle<AdminGrantedInTenant>(AdminPipeline.Handle);
or without:
var builder = EventHandlersBuilder
.Setup()
.Filter<UserAdded>(AdminPipeline.IsAdmin)
.Transform<UserAdded, AdminAdded>(AdminPipeline.ToAdminAdded)
.Handle<AdminAdded>(AdminPipeline.Handle)
.Transform<UserAdded, List<AdminGrantedInTenant>>(AdminPipeline.SendToTenants)
.Handle<AdminGrantedInTenant>(AdminPipeline.Handle);
var eventBus = new EventBus(builder);
Check different ways of defining and integrating Event Handlers:
- Pure functions with Builder
- Pure functions with Dependency Injection
- Classes with Builder
- Classes with Dependency Injection
And how to integrate with MediatR: