Refactor MediatorExtensions for flexible exception handling
Generalize null/empty response handling with SendOrThrowAsync<TResponse, TException>, allowing custom exceptions via a factory delegate. SendOrNotFoundAsync now wraps this method for NotFoundException. Improves type safety, flexibility, and XML docs; avoids treating strings as collections.
This commit is contained in:
@@ -9,6 +9,32 @@ namespace EnvelopeGenerator.Application.Common.Extensions;
|
||||
/// </summary>
|
||||
public static class MediatorExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends a request via MediatR and throws a custom exception produced by <paramref name="exceptionFactory"/>
|
||||
/// when the response is <c>null</c> or an empty collection.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResponse">The expected response type.</typeparam>
|
||||
/// <typeparam name="TException">The exception type to throw.</typeparam>
|
||||
/// <param name="mediator">The mediator instance.</param>
|
||||
/// <param name="request">The MediatR request whose response may be <c>null</c>.</param>
|
||||
/// <param name="exceptionFactory">A factory that creates the exception to throw when the response is absent.</param>
|
||||
/// <param name="cancel">Cancellation token.</param>
|
||||
/// <returns>A guaranteed non-null <typeparamref name="TResponse"/>.</returns>
|
||||
/// <exception cref="Exception">The exception produced by <paramref name="exceptionFactory"/>.</exception>
|
||||
public static async Task<TResponse> SendOrThrowAsync<TResponse, TException>(this IMediator mediator, IRequest<TResponse?> request, Func<TException> exceptionFactory, CancellationToken cancel = default)
|
||||
where TException : Exception
|
||||
{
|
||||
if (await mediator.Send(request, cancel) is TResponse res)
|
||||
{
|
||||
if (res is not string && res is IEnumerable enumerable && !enumerable.Cast<object>().Any())
|
||||
throw exceptionFactory();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
throw exceptionFactory();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a request via MediatR and throws <see cref="NotFoundException"/> when the response is <c>null</c> or an empty collection.
|
||||
/// </summary>
|
||||
@@ -16,23 +42,13 @@ public static class MediatorExtensions
|
||||
/// <param name="mediator">The mediator instance.</param>
|
||||
/// <param name="request">The MediatR request whose response may be <c>null</c>.</param>
|
||||
/// <param name="exceptionMessage">Optional message for the <see cref="NotFoundException"/>.</param>
|
||||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
/// <param name="cancel">Cancellation token.</param>
|
||||
/// <returns>A guaranteed non-null <typeparamref name="TResponse"/>.</returns>
|
||||
/// <exception cref="NotFoundException">Thrown when the response is <c>null</c> or an empty collection.</exception>
|
||||
public static async Task<TResponse> SendOrNotFoundAsync<TResponse>(this IMediator mediator, IRequest<TResponse?> request, string? exceptionMessage, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if(await mediator.Send(request, cancellationToken) is TResponse res)
|
||||
{
|
||||
if(res is IEnumerable enumerable && !enumerable.Cast<object>().Any())
|
||||
throw new NotFoundException(exceptionMessage);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
throw new NotFoundException(exceptionMessage);
|
||||
}
|
||||
public static async Task<TResponse> SendOrNotFoundAsync<TResponse>(this IMediator mediator, IRequest<TResponse?> request, string? exceptionMessage, CancellationToken cancel = default)
|
||||
=> await mediator.SendOrThrowAsync(request, () => new NotFoundException(exceptionMessage ?? $"The requested resource of type {typeof(TResponse).Name} was not found."), cancel);
|
||||
|
||||
/// <inheritdoc cref="SendOrNotFoundAsync{TResponse}(IMediator, IRequest{TResponse}, string, CancellationToken)"/>
|
||||
public static async Task<TResponse> SendOrNotFoundAsync<TResponse>(this IMediator mediator, IRequest<TResponse?> request, CancellationToken cancellationToken = default)
|
||||
=> await mediator.SendOrNotFoundAsync(request, null, cancellationToken);
|
||||
public static async Task<TResponse> SendOrNotFoundAsync<TResponse>(this IMediator mediator, IRequest<TResponse?> request, CancellationToken cancel = default)
|
||||
=> await mediator.SendOrNotFoundAsync(request, null, cancel);
|
||||
}
|
||||
Reference in New Issue
Block a user