Skip to content

Instantly share code, notes, and snippets.

@joacar
Last active June 5, 2018 11:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joacar/827dc313b7ff5b6ede7d804b49640aec to your computer and use it in GitHub Desktop.
Save joacar/827dc313b7ff5b6ede7d804b49640aec to your computer and use it in GitHub Desktop.
Operation MediatR pipeline
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediatR;
namespace TestingMediatR
{
/// <summary>
/// Encapsulates the result of an request operation.
/// </summary>
public class OperationResult
{
protected List<OperationMessage> _messages = new List<OperationMessage>();
/// <summary>
/// List of <see cref="OperationMessage" />s.
/// </summary>
public IReadOnlyList<OperationMessage> Messages => _messages;
/// <summary>
/// The result of the operation.
/// </summary>
/// <value>
/// <c>true</c> if the operation succeeded, otherwise <c>false</c>.
/// </value>
public bool Succeeded { get; protected set; }
/// <summary>
/// Unhandled failure.
/// </summary>
/// <value>
/// The <see cref="Exception" /> thrown when the request was processed.
/// </value>
public Exception Failure { get; protected set; }
public static OperationResult Success { get; } = new OperationResult
{
Succeeded = true
};
public static OperationResult Failed(Exception exception)
{
return new OperationResult
{
Succeeded = false,
Failure = exception
};
}
public static OperationResult Failed(params OperationMessage[] messages)
{
var result = new OperationResult
{
Succeeded = false
};
if (messages != null)
{
result._messages.AddRange(messages);
}
return result;
}
public static implicit operator bool(OperationResult result)
{
return result.Succeeded;
}
public override string ToString()
{
if (Succeeded)
{
return "Succeeded";
}
var message = Failure != null ? Failure.Message : string.Join(",", _messages.Select(_ => _.Code).ToArray());
return $"Failed: {message}";
}
}
/// <summary>
/// </summary>
/// <typeparam name="TResponse"></typeparam>
public class OperationResult<TResponse> : OperationResult
{
public TResponse Response { get; set; }
public static implicit operator TResponse(OperationResult<TResponse> result)
{
return result.Response;
}
public new static OperationResult<TResponse> Success(TResponse data)
{
return new OperationResult<TResponse>
{
Succeeded = true,
Response = data
};
}
public new static OperationResult<TResponse> Failed(Exception exception)
{
return new OperationResult<TResponse>
{
Succeeded = false,
Failure = exception
};
}
public new static OperationResult<TResponse> Failed(params OperationMessage[] messages)
{
var result = new OperationResult<TResponse>
{
Succeeded = false
};
if (messages != null)
{
result._messages.AddRange(messages);
}
return result;
}
}
public abstract class RequestResultWrapper<TRequest> : IRequestHandler<TRequest, OperationResult>
where TRequest : IOperationCommand
{
public async Task<OperationResult> Handle(TRequest request, CancellationToken cancellationToken)
{
try
{
await HandleCore(request, cancellationToken).ConfigureAwait(false);
return OperationResult.Success;
}
catch (Exception exception)
{
return OperationResult.Failed(exception);
}
}
public abstract Task HandleCore(TRequest request, CancellationToken cancellationToken);
}
public abstract class
RequestResultWrapper<TRequest, TResponse> : IRequestHandler<TRequest, OperationResult<TResponse>>
where TRequest : IOperationCommand<TResponse>
{
public async Task<OperationResult<TResponse>> Handle(TRequest request, CancellationToken cancellationToken)
{
try
{
var response = await HandleCore(request, cancellationToken).ConfigureAwait(false);
return OperationResult<TResponse>.Success(response);
}
catch (Exception exception)
{
return OperationResult<TResponse>.Failed(exception);
}
}
public abstract Task<TResponse> HandleCore(TRequest request, CancellationToken cancellationToken);
}
/// <summary>
/// Encapsulate details about any messages during the request operation.
/// </summary>
public class OperationMessage
{
/// <summary>
/// Gets or sets the code for this message.
/// </summary>
/// <value>
/// The code for this message.
/// </value>
/// <remarks>
/// This value should be unique accross the domain.
/// </remarks>
public string Code { get; set; }
/// <summary>
/// Gets or sets the description for this message.
/// </summary>
/// <value>
/// The description for this message.
/// </value>
public string Description { get; set; }
}
/// <summary>
/// Marker interface for performing an operation without a specific result.
/// </summary>
public interface IOperationCommand : IRequest<OperationResult>
{
}
/// <summary>
/// Marker interface for performing an operation expectng to return <typeparamref name="TResult" />.
/// </summary>
/// <typeparam name="TResult">Type of expected result.</typeparam>
public interface IOperationCommand<TResult> : IRequest<OperationResult<TResult>>
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment