Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
3. Notifications:
1. `INotification`
2. `INotificationHandler<TRequestEvent>`
3. Open-generic `INotificationHandler<TNotification> where TNotification : INotification`
> :bulb: **Tip:** *If you're looking for a mediator with the raw performance of hand-written code, DispatchR is built for you.*

## ✨ How to install?
Expand Down Expand Up @@ -62,6 +63,9 @@ public sealed class PingMediatR : IRequest<int> { }
public sealed class PingDispatchR : IRequest<PingDispatchR, ValueTask<int>> { }
```

> [!IMPORTANT]
> Always use a **generic** return type such as `Task<TResult>` or `ValueTask<TResult>`. Using a bare `Task` or `ValueTask` (without a type argument) may prevent the handler from being triggered when pipeline behaviors or validators are present.

## Handler Definition

### MediatR
Expand Down Expand Up @@ -152,7 +156,7 @@ public sealed class CounterStreamRequestMediatR : IStreamRequest<int> { }
1. Sending `TRequest` to `IStreamRequest`

```csharp
public sealed class CounterStreamRequestDispatchR : IStreamRequest<PingDispatchR, ValueTask<int>> { }
public sealed class CounterStreamRequestDispatchR : IStreamRequest<CounterStreamRequestDispatchR, int> { }
```

## Stream Handler Definition
Expand All @@ -171,9 +175,9 @@ public sealed class CounterStreamHandlerMediatR : IStreamRequestHandler<CounterS
### Stream Handler DispatchR (Don't change)

```csharp
public sealed class CounterStreamHandlerDispatchR : IStreamRequestHandler<CounterStreamHandlerDispatchR, int>
public sealed class CounterStreamHandlerDispatchR : IStreamRequestHandler<CounterStreamRequestDispatchR, int>
{
public async IAsyncEnumerable<int> Handle(CounterStreamHandlerDispatchR request, CancellationToken cancellationToken)
public async IAsyncEnumerable<int> Handle(CounterStreamRequestDispatchR request, CancellationToken cancellationToken)
{
yield return 1;
}
Expand Down Expand Up @@ -248,7 +252,7 @@ public sealed class EventHandler(ILogger<Event> logger) : INotificationHandler<E
}
```

### Stream Pipeline DispatchR
### Notification DispatchR
1. Use ___ValueTask___

```csharp
Expand All @@ -264,6 +268,23 @@ public sealed class EventHandler(ILogger<Event> logger) : INotificationHandler<E
}
```

#### Generic notification handler DispatchR
1. A single open-generic handler receives **every** notification type — ideal for cross-cutting concerns such as logging, auditing, or telemetry.

```csharp
public sealed class AllNotificationsLogger<TNotification>(ILogger<AllNotificationsLogger<TNotification>> logger)
: INotificationHandler<TNotification>
where TNotification : INotification
{
public ValueTask Handle(TNotification notification, CancellationToken cancellationToken)
{
logger.LogInformation("[Generic] Received notification of type {NotificationType}: {@Notification}",
typeof(TNotification).Name, notification);
return ValueTask.CompletedTask;
}
}
```

# ⚡ How DispatchR Achieves High Performance

###### DispatchR is designed with one goal in mind: **maximize performance with minimal memory usage**. Here's how it accomplishes that:
Expand Down
Loading