Skip to content

Commit

Permalink
Renamed ProductCreateQuery to ProductCreatedQuery and updated rel…
Browse files Browse the repository at this point in the history
…ated handler and decorator classes. Enhanced `IMediatorHandler` interface with XML documentation for clarity. Improved decorator methods in `ServiceCollectionExtensions` for better consistency and descriptiveness. These changes aim to enhance code clarity, maintainability, and functionality of the mediator pattern.
  • Loading branch information
penyland committed Jan 8, 2025
1 parent 18893a0 commit f1a0f4b
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 16 deletions.
23 changes: 18 additions & 5 deletions samples/MediatorSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,39 @@
services.AddMediatorHandler<ProductCreated, ProductCreatedHandler>()
.Decorate<ProductCreatedDecorator>();

services.AddMediatorHandler<ProductCreateQuery, string, ProductCreateQueryHandler>();
services.AddMediatorHandler<ProductCreatedQuery, string, ProductCreatedQueryHandler>();
services.DecorateMediatorHandler<ProductCreatedQuery, string, ProductCreatedQueryHandlerDecorator>();

var serviceProvider = services.BuildServiceProvider();
var mediator = serviceProvider.GetRequiredService<IMediator>();

await mediator.SendAsync(new ProductCreated(1, "Product 1"));
var result = await mediator.SendAsync<ProductCreateQuery, string>(new ProductCreateQuery());
var result = await mediator.SendAsync<ProductCreatedQuery, string>(new ProductCreatedQuery());

Console.WriteLine("Done");

record ProductCreateQuery : IQuery;
record ProductCreatedQuery : IQuery;

class ProductCreateQueryHandler : IMediatorHandler<ProductCreateQuery, string>
class ProductCreatedQueryHandler : IMediatorHandler<ProductCreatedQuery, string>
{
public Task<Result<string>> HandleAsync(MediatorHandlerContext<ProductCreateQuery> context, CancellationToken cancellationToken = default)
public Task<Result<string>> HandleAsync(MediatorHandlerContext<ProductCreatedQuery> context, CancellationToken cancellationToken = default)
{
Console.WriteLine("ProductCreatedQueryHandler:HandleAsync");
return Task.FromResult(Result.Success("Product 1"));
}
}

class ProductCreatedQueryHandlerDecorator(IMediatorHandler<ProductCreatedQuery, string> inner) : IMediatorHandler<ProductCreatedQuery, string>
{
public async Task<Result<string>> HandleAsync(MediatorHandlerContext<ProductCreatedQuery> context, CancellationToken cancellationToken = default)
{
Console.WriteLine("ProductCreatedQueryHandlerDecorator:HandleAsync");
var result = await inner.HandleAsync(context, cancellationToken);
Console.WriteLine("ProductCreatedQueryHandlerDecorator:HandleAsync:Done");
return result;
}
}

public class LoggingMediator(IMediator inner) : IMediator
{
public async Task<Result> SendAsync<TRequest>(TRequest request, CancellationToken cancellationToken = default) where TRequest : class, ICommand
Expand Down
31 changes: 28 additions & 3 deletions src/Infinity.Toolkit.Experimental/Mediator/Mediator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,53 @@ public interface IQuery { }
public interface IMediatorHandler<TIn>
where TIn : class
{
/// <summary>
/// Represents a handler for a request that does not return a result except for success or failure.
/// </summary>
/// <param name="context">The request context.</param>
/// <param name="cancellationToken">An optional cancellation token.</param>
/// <returns>Returns the result of the request.</returns>
Task<Result> HandleAsync(MediatorHandlerContext<TIn> context, CancellationToken cancellationToken = default);
}

public interface IMediatorHandler<TIn, TResult>
where TIn : class
{
/// <summary>
/// Represents a handler for a request which returns a result.
/// </summary>
/// <param name="context">The request context.</param>
/// <param name="cancellationToken">An optional cancellation token.</param>
/// <returns>Returns the result of the request.</returns>
Task<Result<TResult>> HandleAsync(MediatorHandlerContext<TIn> context, CancellationToken cancellationToken = default);
}

public interface IMediator
{
/// <summary>
/// Sends a request to the mediator, the request is typically a command which does not return a result.
/// </summary>
/// <typeparam name="TRequest">The request type.</typeparam>
/// <param name="request">The content of the request.</param>
/// <param name="cancellationToken">An optional cancellation token.</param>
/// <returns>A success or failure result.</returns>
Task<Result> SendAsync<TRequest>(TRequest request, CancellationToken cancellationToken = default)
where TRequest : class, ICommand;

/// <summary>
/// Sends a request to the mediator, the request is typically a query which returns a result.
/// </summary>
/// <typeparam name="TRequest">The request type.</typeparam>
/// <typeparam name="TResponse">The response type.</typeparam>
/// <param name="request">The content of the request.</param>
/// <param name="cancellationToken">An optional cancellation token.</param>
/// <returns>The result of the request.</returns>
Task<Result<TResponse>> SendAsync<TRequest, TResponse>(TRequest request, CancellationToken cancellationToken = default)
where TRequest : class, IQuery;
}

public class Mediator(IServiceProvider serviceProvider) : IMediator
internal sealed class Mediator(IServiceProvider serviceProvider) : IMediator
{
private readonly IServiceProvider serviceProvider = serviceProvider;

public Task<Result> SendAsync<TRequest>(TRequest request, CancellationToken cancellationToken = default)
where TRequest : class, ICommand
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ public static class ServiceCollectionExtensions
/// <summary>
/// Adds the mediator to the service collection.
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddMediator(this IServiceCollection services)
{
services.TryAddTransient<IMediator, Mediator>();
Expand All @@ -22,7 +20,7 @@ public static IServiceCollection AddMediator(this IServiceCollection services)
/// <typeparam name="TRequest">The request type.</typeparam>
/// <typeparam name="TMediatorHandler">The mediator handler type.</typeparam>
/// <param name="services">The service collection.</param>
/// <returns>A <see cref="MediatorHandlerBuilder"/> instance.</returns>
/// <returns>A <see cref="MediatorHandlerBuilder"/> instance used to configure the mediator handler.</returns>
public static MediatorHandlerBuilder AddMediatorHandler<TRequest, TMediatorHandler>(this IServiceCollection services)
where TRequest : class, ICommand
where TMediatorHandler : class, IMediatorHandler<TRequest>
Expand All @@ -38,7 +36,7 @@ public static MediatorHandlerBuilder AddMediatorHandler<TRequest, TMediatorHandl
/// <typeparam name="TResult">The result type.</typeparam>
/// <typeparam name="TMediatorHandler">The mediator handler type.</typeparam>
/// <param name="services">The service collection.</param>
/// <returns>A <see cref="MediatorHandlerBuilder"/> instance.</returns>
/// <returns>A <see cref="MediatorHandlerBuilder"/> instance used to configure the mediator handler.</returns>
public static MediatorHandlerBuilder AddMediatorHandler<TRequest, TResult, TMediatorHandler>(this IServiceCollection services)
where TRequest : class, IQuery
where TMediatorHandler : class, IMediatorHandler<TRequest, TResult>
Expand All @@ -50,7 +48,8 @@ public static MediatorHandlerBuilder AddMediatorHandler<TRequest, TResult, TMedi
/// <summary>
/// Decorates all registered instance of <see cref="IMediatorHandler{TRequest}"/> using the specified type <typeparamref name="TDecorator"/>.
/// </summary>
/// <param name="services">The services to add to.</param>
/// <typeparam name="TRequest">The request type.</typeparam>
/// <typeparam name="TDecorator">The decorator type.</typeparam>
public static IServiceCollection DecorateMediatorHandler<TRequest, TDecorator>(this IServiceCollection services)
where TDecorator : class, IMediatorHandler<TRequest>
where TRequest : class, ICommand => services.Decorate<IMediatorHandler<TRequest>, TDecorator>();
Expand All @@ -59,11 +58,19 @@ public static IServiceCollection DecorateMediatorHandler<TRequest, TDecorator>(t
/// Decorates all registered instance of <see cref="IMediatorHandler{TQuery, TQueryResult}"/> using the specified type <typeparamref name="TDecorator"/>.
/// </summary>
/// <param name="services">The services to add to.</param>
public static IServiceCollection DecorateMediatorHandler<TQuery, TQueryResult, TDecorator>(this IServiceCollection services)
where TDecorator : class, IMediatorHandler<TQuery, TQueryResult>
where TQuery : class, IQuery => services.Decorate<IMediatorHandler<TQuery, TQueryResult>, TDecorator>();
/// <typeparam name="TRequest">The request type.</typeparam>
/// <typeparam name="TResult">The result type.</typeparam>
/// <typeparam name="TDecorator">The decorator type.</typeparam>
public static IServiceCollection DecorateMediatorHandler<TRequest, TResult, TDecorator>(this IServiceCollection services)
where TDecorator : class, IMediatorHandler<TRequest, TResult>
where TRequest : class, IQuery => services.Decorate<IMediatorHandler<TRequest, TResult>, TDecorator>();
}

/// <summary>
/// A builder used to configure a mediator handler.
/// </summary>
/// <param name="services"></param>
/// <param name="handlerType"></param>
public sealed class MediatorHandlerBuilder(IServiceCollection services, Type handlerType)
{
internal IServiceCollection Services { get; } = services;
Expand All @@ -73,9 +80,19 @@ public sealed class MediatorHandlerBuilder(IServiceCollection services, Type han

public static class MediatorHandlerBuilderExtensions
{
/// <summary>
/// Decorates all registered instances of <see cref="IMediatorHandler{TRequest}"/> using the specified type <typeparamref name="TDecorator"/>.
/// </summary>
/// <typeparam name="TDecorator">The decorator type.</typeparam>
/// <returns>A <see cref="MediatorHandlerBuilder"/> instance used to configure the mediator handler.</returns>
public static MediatorHandlerBuilder Decorate<TDecorator>(this MediatorHandlerBuilder builder)
where TDecorator : class => builder.Decorate(typeof(TDecorator));

/// <summary>
/// Decorates all registered instances of <see cref="IMediatorHandler{TRequest}"/> using the specified type <paramref name="decoratorType"/>.
/// </summary>
/// <param name="decoratorType">The decorator type.</param>
/// <returns>A <see cref="MediatorHandlerBuilder"/> instance used to configure the mediator handler.</returns>
public static MediatorHandlerBuilder Decorate(this MediatorHandlerBuilder builder, Type decoratorType)
{
builder.Services.Decorate(builder.HandlerType, decoratorType);
Expand Down

0 comments on commit f1a0f4b

Please sign in to comment.