Skip to content

Commit 1254be0

Browse files
Copilothasanxdev
andauthored
fix README issues for #44 and add generic notification handler docs (v2.1.2) (#49)
Agent-Logs-Url: https://github.com/hasanxdev/DispatchR/sessions/bf9f2dea-964c-4768-b4e7-31ae7fb7ea59 Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: hasanxdev <30981174+hasanxdev@users.noreply.github.com>
1 parent d4a23d5 commit 1254be0

1 file changed

Lines changed: 25 additions & 4 deletions

File tree

README.md

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
3. Notifications:
3232
1. `INotification`
3333
2. `INotificationHandler<TRequestEvent>`
34+
3. Open-generic `INotificationHandler<TNotification> where TNotification : INotification`
3435
> :bulb: **Tip:** *If you're looking for a mediator with the raw performance of hand-written code, DispatchR is built for you.*
3536
3637
## ✨ How to install?
@@ -62,6 +63,9 @@ public sealed class PingMediatR : IRequest<int> { }
6263
public sealed class PingDispatchR : IRequest<PingDispatchR, ValueTask<int>> { }
6364
```
6465

66+
> [!IMPORTANT]
67+
> 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.
68+
6569
## Handler Definition
6670

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

154158
```csharp
155-
public sealed class CounterStreamRequestDispatchR : IStreamRequest<PingDispatchR, ValueTask<int>> { }
159+
public sealed class CounterStreamRequestDispatchR : IStreamRequest<CounterStreamRequestDispatchR, int> { }
156160
```
157161

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

173177
```csharp
174-
public sealed class CounterStreamHandlerDispatchR : IStreamRequestHandler<CounterStreamHandlerDispatchR, int>
178+
public sealed class CounterStreamHandlerDispatchR : IStreamRequestHandler<CounterStreamRequestDispatchR, int>
175179
{
176-
public async IAsyncEnumerable<int> Handle(CounterStreamHandlerDispatchR request, CancellationToken cancellationToken)
180+
public async IAsyncEnumerable<int> Handle(CounterStreamRequestDispatchR request, CancellationToken cancellationToken)
177181
{
178182
yield return 1;
179183
}
@@ -248,7 +252,7 @@ public sealed class EventHandler(ILogger<Event> logger) : INotificationHandler<E
248252
}
249253
```
250254

251-
### Stream Pipeline DispatchR
255+
### Notification DispatchR
252256
1. Use ___ValueTask___
253257

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

271+
#### Generic notification handler DispatchR
272+
1. A single open-generic handler receives **every** notification type — ideal for cross-cutting concerns such as logging, auditing, or telemetry.
273+
274+
```csharp
275+
public sealed class AllNotificationsLogger<TNotification>(ILogger<AllNotificationsLogger<TNotification>> logger)
276+
: INotificationHandler<TNotification>
277+
where TNotification : INotification
278+
{
279+
public ValueTask Handle(TNotification notification, CancellationToken cancellationToken)
280+
{
281+
logger.LogInformation("[Generic] Received notification of type {NotificationType}: {@Notification}",
282+
typeof(TNotification).Name, notification);
283+
return ValueTask.CompletedTask;
284+
}
285+
}
286+
```
287+
267288
# ⚡ How DispatchR Achieves High Performance
268289

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

0 commit comments

Comments
 (0)