Skip to content
Merged
Show file tree
Hide file tree
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
6 changes: 5 additions & 1 deletion .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,14 @@ jobs:
if: startsWith(github.ref, 'refs/tags/v')
run: echo "version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT"

- name: Pack project
- name: Pack DispatchR project
if: startsWith(github.ref, 'refs/tags/v')
run: dotnet pack src/DispatchR/DispatchR.csproj --configuration Release --no-build -o ./nupkgs /p:PackageVersion=${{ steps.get_version.outputs.version }}

- name: Pack DispatchR Abstractions project
if: startsWith(github.ref, 'refs/tags/v')
run: dotnet pack src/DispatchR.Abstractions/DispatchR.Abstractions.csproj --configuration Release --no-build -o ./nupkgs /p:PackageVersion=${{ steps.get_version.outputs.version }}

- name: Push to NuGet
if: startsWith(github.ref, 'refs/tags/v')
run: dotnet nuget push "./nupkgs/*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json
15 changes: 15 additions & 0 deletions DispatchR.sln
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DispatchR.IntegrationTest",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DispatchR.TestCommon", "tests\DispatchR.TestCommon\DispatchR.TestCommon.csproj", "{F01B6563-64D0-4316-947C-AB75426D9924}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DispatchR.Abstractions", "src\DispatchR.Abstractions\DispatchR.Abstractions.csproj", "{27CFB785-B631-4044-AA90-4B21FA908C0A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -173,6 +175,18 @@ Global
{F01B6563-64D0-4316-947C-AB75426D9924}.Release|x64.Build.0 = Release|Any CPU
{F01B6563-64D0-4316-947C-AB75426D9924}.Release|x86.ActiveCfg = Release|Any CPU
{F01B6563-64D0-4316-947C-AB75426D9924}.Release|x86.Build.0 = Release|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Debug|x64.ActiveCfg = Debug|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Debug|x64.Build.0 = Debug|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Debug|x86.ActiveCfg = Debug|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Debug|x86.Build.0 = Debug|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Release|Any CPU.Build.0 = Release|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Release|x64.ActiveCfg = Release|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Release|x64.Build.0 = Release|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Release|x86.ActiveCfg = Release|Any CPU
{27CFB785-B631-4044-AA90-4B21FA908C0A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -191,5 +205,6 @@ Global
{806030F5-86B1-4EFC-923C-94FF7D32DFC9} = {7F7601D5-C62E-4EA3-8B71-E946A62B4529}
{D8646A62-9FE7-4E79-861C-49391007F98A} = {7F7601D5-C62E-4EA3-8B71-E946A62B4529}
{F01B6563-64D0-4316-947C-AB75426D9924} = {7F7601D5-C62E-4EA3-8B71-E946A62B4529}
{27CFB785-B631-4044-AA90-4B21FA908C0A} = {89F559F6-C217-4D24-9A2F-DF25AE215A7C}
EndGlobalSection
EndGlobal
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# DispatchR 🚀
# <img src="./icon-mini.png" width="25">ispatchR 🚀

![CI](https://github.com/hasanxdev/DispatchR/workflows/Release/badge.svg)
[![codecov](https://codecov.io/github/hasanxdev/dispatchr/graph/badge.svg?token=1FUG5DPUOE)](https://codecov.io/github/hasanxdev/dispatchr)
Expand Down Expand Up @@ -33,6 +33,15 @@
2. `INotificationHandler<TRequestEvent>`
> :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?
```
dotnet add package DispatchR.Mediator
```
You can also separately add only the abstractions, which include the interfaces, in another layer:
```
dotnet add package DispatchR.Mediator.Abstractions
```

# Syntax Comparison: DispatchR vs MediatR

###### In the following, you will see the key differences and implementation details between MediatR and DispatchR.
Expand Down Expand Up @@ -369,11 +378,6 @@ builder.Services.AddScoped<INotificationHandler<Event>, EventHandler>();
2. Manual registration allows for custom pipeline or notification ordering
3. You can implement custom reflection if needed

## ✨ How to install?
```
dotnet add package DispatchR.Mediator
```

# 🧪 Bechmark Result:
> [!IMPORTANT]
> This benchmark was conducted using MediatR version 12.5.0 and the stable release of Mediator Source Generator, version 2.1.7.
Expand Down
Binary file added icon-mini.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icon.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using DispatchR.Requests.Send;
using DispatchR.Abstractions.Send;

namespace AspireModularSample.Modules
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using DispatchR.Requests.Send;
using DispatchR.Abstractions.Send;

namespace AspireModularSample.Modules
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using System.Reflection;
using AspireModularSample.Modules;
using DispatchR;
using DispatchR.Extensions;
using DispatchR.Requests;
using DispatchR.Requests.Send;

var builder = WebApplication.CreateBuilder(args);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Reflection;
using AspireModularSample.Modules;
using DispatchR;
using DispatchR.Extensions;
using DispatchR.Requests;

var builder = WebApplication.CreateBuilder(args);

Expand Down
2 changes: 1 addition & 1 deletion src/Benchmark/Notification/MultiHandlers/MultiHandler0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Benchmark.Notification.MultiHandlers;
public sealed class MultiHandler0
: INotificationHandler<MultiHandlersNotification>,
MediatR.INotificationHandler<MultiHandlersNotification>,
DispatchR.Requests.Notification.INotificationHandler<MultiHandlersNotification>
DispatchR.Abstractions.Notification.INotificationHandler<MultiHandlersNotification>
{
public ValueTask Handle(MultiHandlersNotification notification, CancellationToken cancellationToken) => default;

Expand Down
2 changes: 1 addition & 1 deletion src/Benchmark/Notification/MultiHandlers/MultiHandler1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Benchmark.Notification.MultiHandlers;
public sealed class MultiHandler1
: INotificationHandler<MultiHandlersNotification>,
MediatR.INotificationHandler<MultiHandlersNotification>,
DispatchR.Requests.Notification.INotificationHandler<MultiHandlersNotification>
DispatchR.Abstractions.Notification.INotificationHandler<MultiHandlersNotification>
{
public ValueTask Handle(MultiHandlersNotification notification, CancellationToken cancellationToken) => default;

Expand Down
2 changes: 1 addition & 1 deletion src/Benchmark/Notification/MultiHandlers/MultiHandler2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Benchmark.Notification.MultiHandlers;
public sealed class MultiHandler2
: INotificationHandler<MultiHandlersNotification>,
MediatR.INotificationHandler<MultiHandlersNotification>,
DispatchR.Requests.Notification.INotificationHandler<MultiHandlersNotification>
DispatchR.Abstractions.Notification.INotificationHandler<MultiHandlersNotification>
{
public ValueTask Handle(MultiHandlersNotification notification, CancellationToken cancellationToken) => default;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
namespace Benchmark.Notification.MultiHandlers;

public sealed record MultiHandlersNotification(Guid Id) : INotification, MediatR.INotification,
DispatchR.Requests.Notification.INotification;
DispatchR.Abstractions.Notification.INotification;
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Benchmark.Notification.MultiHandlersAsync;
public sealed class MultiHandlerAsync0
: INotificationHandler<MultiHandlersAsyncNotification>,
MediatR.INotificationHandler<MultiHandlersAsyncNotification>,
DispatchR.Requests.Notification.INotificationHandler<MultiHandlersAsyncNotification>
DispatchR.Abstractions.Notification.INotificationHandler<MultiHandlersAsyncNotification>
{
public async ValueTask Handle(MultiHandlersAsyncNotification notification, CancellationToken cancellationToken) =>
await Task.Yield();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Benchmark.Notification.MultiHandlersAsync;
public sealed class MultiHandlerAsync1
: INotificationHandler<MultiHandlersAsyncNotification>,
MediatR.INotificationHandler<MultiHandlersAsyncNotification>,
DispatchR.Requests.Notification.INotificationHandler<MultiHandlersAsyncNotification>
DispatchR.Abstractions.Notification.INotificationHandler<MultiHandlersAsyncNotification>
{
public async ValueTask Handle(MultiHandlersAsyncNotification notification, CancellationToken cancellationToken) =>
await Task.Yield();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Benchmark.Notification.MultiHandlersAsync;
public sealed class MultiHandlerAsync2
: INotificationHandler<MultiHandlersAsyncNotification>,
MediatR.INotificationHandler<MultiHandlersAsyncNotification>,
DispatchR.Requests.Notification.INotificationHandler<MultiHandlersAsyncNotification>
DispatchR.Abstractions.Notification.INotificationHandler<MultiHandlersAsyncNotification>
{
public async ValueTask Handle(MultiHandlersAsyncNotification notification, CancellationToken cancellationToken) =>
await Task.Yield();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
namespace Benchmark.Notification.MultiHandlersAsync;

public sealed record MultiHandlersAsyncNotification(Guid Id) : INotification, MediatR.INotification,
DispatchR.Requests.Notification.INotification;
DispatchR.Abstractions.Notification.INotification;
4 changes: 2 additions & 2 deletions src/Benchmark/Notification/NotificationBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class NotificationBenchmarks
private IServiceProvider _serviceProvider;
private IServiceScope _serviceScope;
private Mediator.IMediator _mediator;
private DispatchR.Requests.IMediator _dispatchR;
private DispatchR.IMediator _dispatchR;
private Mediator.Mediator _concreteMediator;
private MediatR.IMediator _mediatr;
private SingleHandler.SingleHandler _singleHandler;
Expand Down Expand Up @@ -59,7 +59,7 @@ public void Setup()
_serviceProvider = _serviceScope.ServiceProvider;

_mediator = _serviceProvider.GetRequiredService<Mediator.IMediator>();
_dispatchR = _serviceProvider.GetRequiredService<DispatchR.Requests.IMediator>();
_dispatchR = _serviceProvider.GetRequiredService<DispatchR.IMediator>();
_concreteMediator = _serviceProvider.GetRequiredService<Mediator.Mediator>();
_mediatr = _serviceProvider.GetRequiredService<MediatR.IMediator>();

Expand Down
2 changes: 1 addition & 1 deletion src/Benchmark/Notification/SingleHandler/SingleHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Benchmark.Notification.SingleHandler;
public sealed class SingleHandler
: INotificationHandler<SingleHandlerNotification>,
MediatR.INotificationHandler<SingleHandlerNotification>,
DispatchR.Requests.Notification.INotificationHandler<SingleHandlerNotification>
DispatchR.Abstractions.Notification.INotificationHandler<SingleHandlerNotification>
{
public ValueTask Handle(SingleHandlerNotification notification, CancellationToken cancellationToken) => default;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
namespace Benchmark.Notification.SingleHandler;

public sealed record SingleHandlerNotification(Guid Id) : INotification, MediatR.INotification,
DispatchR.Requests.Notification.INotification;
DispatchR.Abstractions.Notification.INotification;
3 changes: 1 addition & 2 deletions src/Benchmark/SendRequest/DispatchRCommands.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using DispatchR.Requests;
using DispatchR.Requests.Send;
using DispatchR.Abstractions.Send;

namespace Benchmark.SendRequest;

Expand Down
8 changes: 4 additions & 4 deletions src/Benchmark/SendRequest/MediatRVsDispatchRBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class MediatRVsDispatchBenchmark
private IServiceScope _serviceScopeForMediatRWithoutPipeline;
private IServiceScope _serviceScopeForMediatSgWithoutPipeline;
private IServiceScope _serviceScopeForDispatchRWithoutPipeline;
private DispatchR.Requests.IMediator _dispatchRWithoutPipeline;
private DispatchR.IMediator _dispatchRWithoutPipeline;
private IMediator _mediatRWithoutPipeline;
private Mediator.IMediator _mediatSgWithoutPipeline;
private static readonly PingDispatchR StaticDispatchR = new();
Expand Down Expand Up @@ -42,7 +42,7 @@ public void Setup()
});
withoutPipelineServices.AddDispatchR(typeof(PingDispatchR).Assembly, withPipelines: false);
var buildServicesWithoutPipeline = withoutPipelineServices.BuildServiceProvider();
_dispatchRWithoutPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<DispatchR.Requests.IMediator>();
_dispatchRWithoutPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<DispatchR.IMediator>();
_mediatRWithoutPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<MediatR.IMediator>();
_mediatSgWithoutPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<Mediator.IMediator>();
_serviceScopeForMediatRWithoutPipeline = buildServicesWithoutPipeline.CreateScope();
Expand Down Expand Up @@ -167,7 +167,7 @@ public ValueTask<int> DispatchR_SendRequest_With_ExistRequest_GetMediator()
{
return _serviceScopeForDispatchRWithoutPipeline
.ServiceProvider
.GetRequiredService<DispatchR.Requests.IMediator>()
.GetRequiredService<DispatchR.IMediator>()
.Send(StaticDispatchR, CancellationToken.None);
}

Expand Down Expand Up @@ -247,7 +247,7 @@ public async Task<int> DispatchR_SendRequest_With_ExistRequest_GetMediator_Exist
var result = 0;
await Parallel.ForEachAsync(ScopesForDispatchRWithoutPipeline, async (scope, ct) =>
{
result = await scope.ServiceProvider.GetRequiredService<DispatchR.Requests.IMediator>()
result = await scope.ServiceProvider.GetRequiredService<DispatchR.IMediator>()
.Send(StaticDispatchR, CancellationToken.None);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class MediatRVsDispatchWithPipelineRBenchmark
private IServiceScope _serviceScopeForMediatRWithPipeline;
private IServiceScope _serviceScopeForMediatSgWithPipeline;
private IServiceScope _serviceScopeForDispatchRWithPipeline;
private DispatchR.Requests.IMediator _dispatchRWithPipeline;
private DispatchR.IMediator _dispatchRWithPipeline;
private IMediator _mediatRWithPipeline;
private Mediator.IMediator _mediatSgWithPipeline;
private static readonly PingDispatchR StaticDispatchR = new();
Expand Down Expand Up @@ -49,7 +49,7 @@ public void Setup()

withPipelineServices.AddDispatchR(typeof(PingDispatchR).Assembly);
var buildServicesWithoutPipeline = withPipelineServices.BuildServiceProvider();
_dispatchRWithPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<DispatchR.Requests.IMediator>();
_dispatchRWithPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<DispatchR.IMediator>();
_mediatRWithPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<MediatR.IMediator>();
_mediatSgWithPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<Mediator.IMediator>();
_serviceScopeForMediatRWithPipeline = buildServicesWithoutPipeline.CreateScope();
Expand Down Expand Up @@ -170,7 +170,7 @@ public ValueTask<int> DispatchR_SendRequest_ExistRequest_GetMediator()
{
return _serviceScopeForDispatchRWithPipeline
.ServiceProvider
.GetRequiredService<DispatchR.Requests.IMediator>()
.GetRequiredService<DispatchR.IMediator>()
.Send(StaticDispatchR, CancellationToken.None);
}

Expand Down Expand Up @@ -250,7 +250,7 @@ public async Task<int> DispatchR_SendRequest_ExistRequest_GetMediator_ExistScope
var result = 0;
await Parallel.ForEachAsync(ScopesForDispatchRWithPipeline, async (scope, ct) =>
{
result = await scope.ServiceProvider.GetRequiredService<DispatchR.Requests.IMediator>()
result = await scope.ServiceProvider.GetRequiredService<DispatchR.IMediator>()
.Send(StaticDispatchR, CancellationToken.None);
});

Expand Down
3 changes: 1 addition & 2 deletions src/Benchmark/StreamRequest/StreamDispatchRCommands.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
using System.Runtime.CompilerServices;
using DispatchR.Requests;
using DispatchR.Requests.Stream;
using DispatchR.Abstractions.Stream;

namespace Benchmark.StreamRequest;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class StreamMediatRVsDispatchBenchmark
private IServiceScope _serviceScopeForMediatRWithoutPipeline;
private IServiceScope _serviceScopeForMediatSgWithoutPipeline;
private IServiceScope _serviceScopeForDispatchRWithoutPipeline;
private DispatchR.Requests.IMediator _dispatchRWithoutPipeline;
private DispatchR.IMediator _dispatchRWithoutPipeline;
private IMediator _mediatRWithoutPipeline;
private Mediator.IMediator _mediatSgWithoutPipeline;
private static readonly PingStreamDispatchR StaticStreamDispatchR = new();
Expand Down Expand Up @@ -42,7 +42,7 @@ public void Setup()
});
withoutPipelineServices.AddDispatchR(typeof(PingStreamDispatchR).Assembly, withPipelines: false);
var buildServicesWithoutPipeline = withoutPipelineServices.BuildServiceProvider();
_dispatchRWithoutPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<DispatchR.Requests.IMediator>();
_dispatchRWithoutPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<DispatchR.IMediator>();
_mediatRWithoutPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<MediatR.IMediator>();
_mediatSgWithoutPipeline = buildServicesWithoutPipeline.CreateScope().ServiceProvider.GetRequiredService<Mediator.IMediator>();
_serviceScopeForMediatRWithoutPipeline = buildServicesWithoutPipeline.CreateScope();
Expand Down Expand Up @@ -208,7 +208,7 @@ public async Task<int> DispatchR_StreamRequest_With_ExistRequest_GetMediator()
{
var mediator = _serviceScopeForDispatchRWithoutPipeline
.ServiceProvider
.GetRequiredService<DispatchR.Requests.IMediator>();
.GetRequiredService<DispatchR.IMediator>();

var last = 0;
await foreach (var response in mediator.CreateStream(StaticStreamDispatchR, CancellationToken.None).ConfigureAwait(false))
Expand Down Expand Up @@ -309,7 +309,7 @@ public async Task<int> DispatchR_StreamRequest_With_ExistRequest_GetMediator_Exi
var result = 0;
await Parallel.ForEachAsync(ScopesForDispatchRWithoutPipeline, async (scope, ct) =>
{
var mediator = scope.ServiceProvider.GetRequiredService<DispatchR.Requests.IMediator>();
var mediator = scope.ServiceProvider.GetRequiredService<DispatchR.IMediator>();
await foreach (var response in mediator.CreateStream(StaticStreamDispatchR, CancellationToken.None).ConfigureAwait(false))
{
result = response;
Expand Down
Loading