Files
Umbraco-CMS/src/Umbraco.Core/Services/OperationResult.cs
2017-11-30 13:57:40 +01:00

239 lines
11 KiB
C#

using System;
using Umbraco.Core.Events;
namespace Umbraco.Core.Services
{
// FIXME
// no need for Attempt<OperationResult> - the operation result SHOULD KNOW if it's a success or a failure!
// but then each WhateverResultType must
/// <summary>
/// Represents the result of a service operation.
/// </summary>
/// <typeparam name="TResultType">The type of the result type.</typeparam>
public class OperationResult<TResultType>
where TResultType : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="OperationResult{TResultType}"/> class.
/// </summary>
public OperationResult(TResultType result, EventMessages eventMessages)
{
Result = result;
EventMessages = eventMessages;
}
static OperationResult()
{
// ensure that TResultType is an enum and the underlying type is byte
// so we can safely cast in Success and test against 128 for failures
var type = typeof(TResultType);
if (type.IsEnum == false)
throw new InvalidOperationException($"Type {type} is not an enum.");
if (Enum.GetUnderlyingType(type) != typeof (byte))
throw new InvalidOperationException($"Enum {type} underlying type is not <byte>.");
}
/// <summary>
/// Gets a value indicating whether the operation was successful.
/// </summary>
public bool Success => ((byte) (object) Result & 128) == 0; // we *know* it's a byte
/// <summary>
/// Gets the result of the operation.
/// </summary>
public TResultType Result { get; }
/// <summary>
/// Gets the event messages produced by the operation.
/// </summary>
public EventMessages EventMessages { get; }
}
/// <inheritdoc />
/// <summary>
/// Represents the result of a service operation for a given entity.
/// </summary>
/// <typeparam name="TResultType">The type of the result type.</typeparam>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
public class OperationResult<TResultType, TEntity> : OperationResult<TResultType>
where TResultType : struct
{
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="OperationResult{TResultType, TEntity}"/> class.
/// </summary>
/// <param name="result">The status of the operation.</param>
/// <param name="eventMessages">Event messages produced by the operation.</param>
public OperationResult(TResultType result, EventMessages eventMessages)
: base(result, eventMessages)
{ }
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="OperationResult{TResultType, TEntity}"/> class.
/// </summary>
public OperationResult(TResultType result, EventMessages eventMessages, TEntity entity)
: base(result, eventMessages)
{
Entity = entity;
}
/// <summary>
/// Gets the entity.
/// </summary>
public TEntity Entity { get; }
}
/// <inheritdoc />
/// <summary>
/// Represents the default operation result.
/// </summary>
public class OperationResult : OperationResult<OperationResultType>
{
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="OperationResult" /> class with a status and event messages.
/// </summary>
/// <param name="result">The status of the operation.</param>
/// <param name="eventMessages">Event messages produced by the operation.</param>
public OperationResult(OperationResultType result, EventMessages eventMessages)
: base(result, eventMessages)
{ }
public static OperationResult Succeed(EventMessages eventMessages)
{
return new OperationResult(OperationResultType.Success, eventMessages);
}
public static OperationResult Cancel(EventMessages eventMessages)
{
return new OperationResult(OperationResultType.FailedCancelledByEvent, eventMessages);
}
// fixme wtf?
internal static class Attempt
{
/// <summary>
/// Creates a successful operation attempt.
/// </summary>
/// <param name="eventMessages">The event messages produced by the operation.</param>
/// <returns>A new attempt instance.</returns>
public static Attempt<OperationResult> Succeed(EventMessages eventMessages)
{
return Core.Attempt.Succeed(new OperationResult(OperationResultType.Success, eventMessages));
}
public static Attempt<OperationResult<OperationResultType, TValue>> Succeed<TValue>(EventMessages eventMessages)
{
return Core.Attempt.Succeed(new OperationResult<OperationResultType, TValue>(OperationResultType.Success, eventMessages));
}
public static Attempt<OperationResult<OperationResultType, TValue>> Succeed<TValue>(EventMessages eventMessages, TValue value)
{
return Core.Attempt.Succeed(new OperationResult<OperationResultType, TValue>(OperationResultType.Success, eventMessages, value));
}
public static Attempt<OperationResult<TStatusType>> Succeed<TStatusType>(TStatusType statusType, EventMessages eventMessages)
where TStatusType : struct
{
return Core.Attempt.Succeed(new OperationResult<TStatusType>(statusType, eventMessages));
}
public static Attempt<OperationResult<TStatusType, TValue>> Succeed<TStatusType, TValue>(TStatusType statusType, EventMessages eventMessages, TValue value)
where TStatusType : struct
{
return Core.Attempt.Succeed(new OperationResult<TStatusType, TValue>(statusType, eventMessages, value));
}
/// <summary>
/// Creates a successful operation attempt indicating that nothing was done.
/// </summary>
/// <param name="eventMessages">The event messages produced by the operation.</param>
/// <returns>A new attempt instance.</returns>
public static Attempt<OperationResult> NoOperation(EventMessages eventMessages)
{
return Core.Attempt.Succeed(new OperationResult(OperationResultType.NoOperation, eventMessages));
}
/// <summary>
/// Creates a failed operation attempt indicating that the operation has been cancelled.
/// </summary>
/// <param name="eventMessages">The event messages produced by the operation.</param>
/// <returns>A new attempt instance.</returns>
public static Attempt<OperationResult> Cancel(EventMessages eventMessages)
{
return Core.Attempt.Fail(new OperationResult(OperationResultType.FailedCancelledByEvent, eventMessages));
}
public static Attempt<OperationResult<OperationResultType, TValue>> Cancel<TValue>(EventMessages eventMessages)
{
return Core.Attempt.Fail(new OperationResult<OperationResultType, TValue>(OperationResultType.FailedCancelledByEvent, eventMessages));
}
public static Attempt<OperationResult<OperationResultType, TValue>> Cancel<TValue>(EventMessages eventMessages, TValue value)
{
return Core.Attempt.Fail(new OperationResult<OperationResultType, TValue>(OperationResultType.FailedCancelledByEvent, eventMessages, value));
}
/// <summary>
/// Creates a failed operation attempt indicating that an exception was thrown during the operation.
/// </summary>
/// <param name="eventMessages">The event messages produced by the operation.</param>
/// <param name="exception">The exception that caused the operation to fail.</param>
/// <returns>A new attempt instance.</returns>
public static Attempt<OperationResult> Fail(EventMessages eventMessages, Exception exception)
{
eventMessages.Add(new EventMessage("", exception.Message, EventMessageType.Error));
return Core.Attempt.Fail(new OperationResult(OperationResultType.FailedExceptionThrown, eventMessages), exception);
}
public static Attempt<OperationResult<OperationResultType, TValue>> Fail<TValue>(EventMessages eventMessages, Exception exception)
{
return Core.Attempt.Fail(new OperationResult<OperationResultType, TValue>(OperationResultType.FailedExceptionThrown, eventMessages), exception);
}
public static Attempt<OperationResult<TStatusType>> Fail<TStatusType>(TStatusType statusType, EventMessages eventMessages)
where TStatusType : struct
{
return Core.Attempt.Fail(new OperationResult<TStatusType>(statusType, eventMessages));
}
public static Attempt<OperationResult<TStatusType>> Fail<TStatusType>(TStatusType statusType, EventMessages eventMessages, Exception exception)
where TStatusType : struct
{
return Core.Attempt.Fail(new OperationResult<TStatusType>(statusType, eventMessages), exception);
}
public static Attempt<OperationResult<TStatusType, TValue>> Fail<TStatusType, TValue>(TStatusType statusType, EventMessages eventMessages)
where TStatusType : struct
{
return Core.Attempt.Fail(new OperationResult<TStatusType, TValue>(statusType, eventMessages));
}
public static Attempt<OperationResult<TStatusType, TValue>> Fail<TStatusType, TValue>(TStatusType statusType, EventMessages eventMessages, TValue value)
where TStatusType : struct
{
return Core.Attempt.Fail(new OperationResult<TStatusType, TValue>(statusType, eventMessages, value));
}
public static Attempt<OperationResult<TStatusType, TValue>> Fail<TStatusType, TValue>(TStatusType statusType, EventMessages eventMessages, Exception exception)
where TStatusType : struct
{
return Core.Attempt.Fail(new OperationResult<TStatusType, TValue>(statusType, eventMessages), exception);
}
public static Attempt<OperationResult<TStatusType, TValue>> Fail<TStatusType, TValue>(TStatusType statusType, EventMessages eventMessages, TValue value, Exception exception)
where TStatusType : struct
{
return Core.Attempt.Fail(new OperationResult<TStatusType, TValue>(statusType, eventMessages, value), exception);
}
public static Attempt<OperationResult<OperationResultType, TValue>> Cannot<TValue>(EventMessages eventMessages)
{
return Core.Attempt.Fail(new OperationResult<OperationResultType, TValue>(OperationResultType.FailedCannot, eventMessages));
}
}
}
}