├── icon.jpg
├── TS.MediatR.slnx
├── Options
└── MediatROptions.cs
├── LICENSE.txt
├── IRequest.cs
├── TS.MediatR.csproj
├── .gitattributes
├── ServiceRegistrar.cs
├── ISender.cs
├── README.md
└── .gitignore
/icon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TS-NuGet-Packages/TS.MediatR/HEAD/icon.jpg
--------------------------------------------------------------------------------
/TS.MediatR.slnx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Options/MediatROptions.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | namespace TS.MediatR.Options;
4 | public sealed class MediatROptions
5 | {
6 | internal List Assemblies { get; set; } = new();
7 | internal List PipelineBehaviors { get; set; } = new();
8 |
9 | public void RegisterServicesFromAssembly(Assembly assembly)
10 | {
11 | Assemblies.Add(assembly);
12 | }
13 |
14 | public void RegisterServicesFromAssemblies(params Assembly[] assemblies)
15 | {
16 | Assemblies.AddRange(assemblies);
17 | }
18 |
19 | public void AddOpenBehavior(Type behaviorType)
20 | {
21 | PipelineBehaviors.Add(behaviorType);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Taner Saydam
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/IRequest.cs:
--------------------------------------------------------------------------------
1 | namespace TS.MediatR;
2 | public interface IRequest { }
3 | public interface IRequest { }
4 |
5 | public interface IRequestHandler where TRequest : IRequest
6 | {
7 | Task Handle(TRequest request, CancellationToken cancellationToken);
8 | }
9 | public interface IRequestHandler where TRequest : IRequest
10 | {
11 | Task Handle(TRequest request, CancellationToken cancellationToken);
12 | }
13 |
14 | public delegate Task RequestHandlerDelegate();
15 | public delegate Task RequestHandlerDelegate();
16 |
17 | public interface IPipelineBehavior
18 | where TRequest : IRequest
19 | {
20 | Task Handle(
21 | TRequest request,
22 | RequestHandlerDelegate next,
23 | CancellationToken cancellationToken = default
24 | );
25 | }
26 |
27 | public interface IPipelineBehavior
28 | where TRequest : IRequest
29 | {
30 | Task Handle(
31 | TRequest request,
32 | RequestHandlerDelegate next,
33 | CancellationToken cancellationToken = default
34 | );
35 | }
36 |
37 | public interface INotification { }
38 | public interface INotificationHandler where TNotification : INotification
39 | {
40 | Task Handle(TNotification notification, CancellationToken cancellationToken = default);
41 | }
--------------------------------------------------------------------------------
/TS.MediatR.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net10.0
5 | enable
6 | enable
7 | True
8 | 10.0.0
9 | Taner Saydam
10 | Taner Saydam
11 | Lightweight and flexible Mediator library for .NET with support for CQRS, pipeline behaviors, and notifications. Built for clean and scalable architecture.
12 | icon.jpg
13 | README.md
14 | https://github.com/TS-NuGet-Packages/TS.MediatR
15 | https://github.com/TS-NuGet-Packages/TS.MediatR
16 | Mediator;CQRS;MediatR;Pipeline;Notification;RequestHandler;DependencyInjection;Messaging;CleanArchitecture;DotNet;Middleware
17 | LICENSE.txt
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | True
27 | \
28 |
29 |
30 | True
31 | \
32 |
33 |
34 | True
35 | \
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/ServiceRegistrar.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using TS.MediatR.Options;
3 |
4 | namespace TS.MediatR;
5 |
6 | public static class ServiceRegistrar
7 | {
8 | public static IServiceCollection AddMediatR(
9 | this IServiceCollection services,
10 | Action options)
11 | {
12 | if (options is null) throw new ArgumentNullException(nameof(options));
13 |
14 | var config = new MediatROptions();
15 | options(config);
16 |
17 | #region IReuqestHandler
18 | foreach (var assembly in config.Assemblies)
19 | {
20 | var types = assembly.GetTypes().Where(t => !t.IsInterface && !t.IsAbstract);
21 |
22 | var handlerTypes = types.SelectMany(t => t
23 | .GetInterfaces()
24 | .Where(i => i.IsGenericType && (
25 | i.GetGenericTypeDefinition() == typeof(IRequestHandler<>)
26 | || i.GetGenericTypeDefinition() == typeof(IRequestHandler<,>)
27 | ))
28 | .Select(s => new { Interface = s, Impletation = t })
29 | );
30 |
31 | services.AddScoped();
32 |
33 | foreach (var item in handlerTypes)
34 | {
35 | services.AddScoped(item.Interface, item.Impletation);
36 | }
37 | }
38 | #endregion
39 |
40 | #region IPipelineBehavior
41 | foreach (var pipeline in config.PipelineBehaviors)
42 | {
43 | var genericArg = pipeline.GetGenericArguments().Length;
44 |
45 | if (genericArg == 1)
46 | {
47 | services.AddScoped(typeof(IPipelineBehavior<>), pipeline);
48 | }
49 | else if (genericArg == 2)
50 | {
51 | services.AddScoped(typeof(IPipelineBehavior<,>), pipeline);
52 | }
53 | else
54 | {
55 | throw new ArgumentOutOfRangeException(nameof(genericArg));
56 | }
57 | }
58 | #endregion
59 |
60 | #region INotificationHandler
61 | foreach (var assembly in config.Assemblies)
62 | {
63 | var types = assembly.GetTypes().Where(t => !t.IsInterface && !t.IsAbstract);
64 |
65 | var handlerTypes = types
66 | .SelectMany(t => t
67 | .GetInterfaces()
68 | .Where(t => t.IsGenericType && (t.GetGenericTypeDefinition() == typeof(INotificationHandler<>)))
69 | .Select(s => new { Interface = s, Implementation = t }));
70 |
71 | foreach (var handler in handlerTypes)
72 | {
73 | services.AddScoped(handler.Interface, handler.Implementation);
74 | }
75 | }
76 | #endregion
77 |
78 | return services;
79 | }
80 | }
--------------------------------------------------------------------------------
/ISender.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 |
3 | namespace TS.MediatR;
4 |
5 | public interface ISender
6 | {
7 | Task Send(IRequest request, CancellationToken cancellationToken = default);
8 | Task Send(IRequest request, CancellationToken cancellationToken = default);
9 | Task Publish(INotification notification, CancellationToken cancellationToken = default);
10 | }
11 |
12 | public sealed class Sender(
13 | IServiceProvider serviceProvider) : ISender
14 | {
15 | public async Task Send(IRequest request, CancellationToken cancellationToken = default)
16 | {
17 | var sp = serviceProvider;
18 | var interfaceType = typeof(IRequestHandler<>).MakeGenericType(request.GetType());
19 | var pipelineType = typeof(IPipelineBehavior<>).MakeGenericType(request.GetType());
20 |
21 | RequestHandlerDelegate handlerDelete = () =>
22 | {
23 | var handler = sp.GetRequiredService(interfaceType);
24 | var method = interfaceType.GetMethod("Handle")!;
25 | return (Task)method.Invoke(handler, new object[] { request, cancellationToken })!;
26 | };
27 |
28 | var behaviors = (IEnumerable