< Summary

Information
Class: AsiBackbone.Core.Results.OperationResult
Assembly: AsiBackbone.Core
File(s): /home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Results/OperationResult.cs
Line coverage
100%
Covered lines: 81
Uncovered lines: 0
Coverable lines: 81
Total lines: 348
Line coverage: 100%
Branch coverage
100%
Covered branches: 36
Total branches: 36
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.cctor()100%11100%
.ctor(...)100%11100%
get_Succeeded()100%11100%
get_Failed()100%11100%
get_Reasons()100%11100%
get_ReasonCodes()100%11100%
get_Warnings()100%11100%
get_HasWarnings()100%11100%
Success()100%11100%
Success(...)100%11100%
Success(...)100%11100%
Success(...)100%11100%
Failure(...)100%11100%
Failure(...)100%11100%
Failure(...)100%11100%
Failure(...)100%11100%
Failure(...)100%11100%
Failure(...)100%11100%
Failure(...)100%11100%
Failure(...)100%11100%
Failure()100%11100%
Failure()100%11100%
ToFailure()100%22100%
NormalizeReasons(...)100%11100%
NormalizeReasons(...)100%2424100%
CreateFallbackReason(...)100%11100%
NormalizeWarnings(...)100%66100%
CreateReasonCodes(...)100%44100%

File(s)

/home/runner/work/AsiBackbone/AsiBackbone/src/AsiBackbone.Core/Results/OperationResult.cs

#LineLine coverage
 1using System.Collections.ObjectModel;
 2
 3namespace AsiBackbone.Core.Results;
 4
 5/// <summary>
 6/// Represents the framework-neutral outcome of an operation.
 7/// </summary>
 8public class OperationResult
 9{
 10    private const string DefaultFailureCode = "operation.failed";
 11    private const string DefaultFailureMessage = "Operation failed.";
 12
 513    private static readonly IReadOnlyList<OperationReason> EmptyReasons =
 514        Array.AsReadOnly(Array.Empty<OperationReason>());
 15
 516    private static readonly IReadOnlyList<string> EmptyWarnings =
 517        Array.AsReadOnly(Array.Empty<string>());
 18
 519    private static readonly ReadOnlyCollection<string> EmptyReasonCodes =
 520        Array.AsReadOnly(Array.Empty<string>());
 21
 22    /// <summary>
 23    /// Initializes a new instance of the <see cref="OperationResult"/> class.
 24    /// </summary>
 25    /// <param name="succeeded">A value indicating whether the operation succeeded.</param>
 26    /// <param name="reasons">The reasons associated with the operation result.</param>
 27    /// <param name="warnings">The warnings associated with the operation result.</param>
 8928    protected OperationResult(
 8929        bool succeeded,
 8930        IReadOnlyList<OperationReason> reasons,
 8931        IReadOnlyList<string> warnings)
 32    {
 8933        Succeeded = succeeded;
 8934        Reasons = reasons;
 8935        Warnings = warnings;
 8936        ReasonCodes = CreateReasonCodes(reasons);
 8937    }
 38
 39    /// <summary>
 40    /// Gets a value indicating whether the operation succeeded.
 41    /// </summary>
 8442    public bool Succeeded { get; }
 43
 44    /// <summary>
 45    /// Gets a value indicating whether the operation failed.
 46    /// </summary>
 847    public bool Failed => !Succeeded;
 48
 49    /// <summary>
 50    /// Gets the reasons associated with the operation result.
 51    /// </summary>
 1852    public IReadOnlyList<OperationReason> Reasons { get; }
 53
 54    /// <summary>
 55    /// Gets machine-readable reason codes associated with the operation result.
 56    /// </summary>
 4257    public IReadOnlyList<string> ReasonCodes { get; }
 58
 59    /// <summary>
 60    /// Gets human-readable warning messages associated with the operation result.
 61    /// </summary>
 2862    public IReadOnlyList<string> Warnings { get; }
 63
 64    /// <summary>
 65    /// Gets a value indicating whether the operation result has warning messages.
 66    /// </summary>
 1567    public bool HasWarnings => Warnings.Count > 0;
 68
 69    /// <summary>
 70    /// Creates a successful operation result.
 71    /// </summary>
 72    /// <returns>A successful operation result.</returns>
 73    public static OperationResult Success()
 74    {
 1275        return new OperationResult(true, EmptyReasons, EmptyWarnings);
 76    }
 77
 78    /// <summary>
 79    /// Creates a successful operation result with warnings.
 80    /// </summary>
 81    /// <param name="warnings">The warnings associated with the successful result.</param>
 82    /// <returns>A successful operation result.</returns>
 83    public static OperationResult Success(IEnumerable<string> warnings)
 84    {
 585        return new OperationResult(true, EmptyReasons, NormalizeWarnings(warnings));
 86    }
 87
 88    /// <summary>
 89    /// Creates a successful operation result with a value.
 90    /// </summary>
 91    /// <typeparam name="TValue">The result value type.</typeparam>
 92    /// <param name="value">The operation value.</param>
 93    /// <returns>A successful operation result.</returns>
 94    public static OperationResult<TValue> Success<TValue>(TValue value)
 95    {
 2796        return new OperationResult<TValue>(value, EmptyReasons, EmptyWarnings);
 97    }
 98
 99    /// <summary>
 100    /// Creates a successful operation result with a value and warnings.
 101    /// </summary>
 102    /// <typeparam name="TValue">The result value type.</typeparam>
 103    /// <param name="value">The operation value.</param>
 104    /// <param name="warnings">The warnings associated with the successful result.</param>
 105    /// <returns>A successful operation result.</returns>
 106    public static OperationResult<TValue> Success<TValue>(TValue value, IEnumerable<string> warnings)
 107    {
 1108        return new OperationResult<TValue>(value, EmptyReasons, NormalizeWarnings(warnings));
 109    }
 110
 111    /// <summary>
 112    /// Creates a failed operation result.
 113    /// </summary>
 114    /// <param name="code">The machine-readable reason code.</param>
 115    /// <param name="message">The human-readable reason message.</param>
 116    /// <returns>A failed operation result.</returns>
 117    public static OperationResult Failure(string code, string message)
 118    {
 27119        return Failure(OperationReason.Create(code, message));
 120    }
 121
 122    /// <summary>
 123    /// Creates a failed operation result.
 124    /// </summary>
 125    /// <typeparam name="TValue">The result value type.</typeparam>
 126    /// <param name="code">The machine-readable reason code.</param>
 127    /// <param name="message">The human-readable reason message.</param>
 128    /// <returns>A failed operation result.</returns>
 129    public static OperationResult<TValue> Failure<TValue>(string code, string message)
 130    {
 4131        return Failure<TValue>(OperationReason.Create(code, message));
 132    }
 133
 134    /// <summary>
 135    /// Creates a failed operation result.
 136    /// </summary>
 137    /// <param name="reason">The reason associated with the failed result.</param>
 138    /// <returns>A failed operation result.</returns>
 139    public static OperationResult Failure(OperationReason reason)
 140    {
 28141        ArgumentNullException.ThrowIfNull(reason);
 142
 27143        return new OperationResult(false, Array.AsReadOnly([reason]), EmptyWarnings);
 144    }
 145
 146    /// <summary>
 147    /// Creates a failed operation result.
 148    /// </summary>
 149    /// <typeparam name="TValue">The result value type.</typeparam>
 150    /// <param name="reason">The reason associated with the failed result.</param>
 151    /// <returns>A failed operation result.</returns>
 152    public static OperationResult<TValue> Failure<TValue>(OperationReason reason)
 153    {
 5154        ArgumentNullException.ThrowIfNull(reason);
 155
 4156        return new OperationResult<TValue>(Array.AsReadOnly([reason]), EmptyWarnings);
 157    }
 158
 159    /// <summary>
 160    /// Creates a failed operation result.
 161    /// </summary>
 162    /// <param name="reasons">The reasons associated with the failed result.</param>
 163    /// <returns>A failed operation result.</returns>
 164    public static OperationResult Failure(IEnumerable<OperationReason> reasons)
 165    {
 7166        return new OperationResult(false, NormalizeReasons(reasons), EmptyWarnings);
 167    }
 168
 169    /// <summary>
 170    /// Creates a failed operation result.
 171    /// </summary>
 172    /// <typeparam name="TValue">The result value type.</typeparam>
 173    /// <param name="reasons">The reasons associated with the failed result.</param>
 174    /// <returns>A failed operation result.</returns>
 175    public static OperationResult<TValue> Failure<TValue>(IEnumerable<OperationReason> reasons)
 176    {
 2177        return new OperationResult<TValue>(NormalizeReasons(reasons), EmptyWarnings);
 178    }
 179
 180    /// <summary>
 181    /// Creates a failed operation result with warnings.
 182    /// </summary>
 183    /// <param name="reasons">The reasons associated with the failed result.</param>
 184    /// <param name="warnings">The warnings associated with the failed result.</param>
 185    /// <returns>A failed operation result.</returns>
 186    public static OperationResult Failure(
 187        IEnumerable<OperationReason> reasons,
 188        IEnumerable<string> warnings)
 189    {
 1190        return new OperationResult(false, NormalizeReasons(reasons), NormalizeWarnings(warnings));
 191    }
 192
 193    /// <summary>
 194    /// Creates a failed operation result with warnings.
 195    /// </summary>
 196    /// <typeparam name="TValue">The result value type.</typeparam>
 197    /// <param name="reasons">The reasons associated with the failed result.</param>
 198    /// <param name="warnings">The warnings associated with the failed result.</param>
 199    /// <returns>A failed operation result.</returns>
 200    public static OperationResult<TValue> Failure<TValue>(
 201        IEnumerable<OperationReason> reasons,
 202        IEnumerable<string> warnings)
 203    {
 1204        return new OperationResult<TValue>(NormalizeReasons(reasons), NormalizeWarnings(warnings));
 205    }
 206
 207    /// <summary>
 208    /// Creates a failed operation result using the default failure reason.
 209    /// </summary>
 210    /// <returns>A failed operation result.</returns>
 211    public static OperationResult Failure()
 212    {
 1213        return Failure(DefaultFailureCode, DefaultFailureMessage);
 214    }
 215
 216    /// <summary>
 217    /// Creates a failed operation result using the default failure reason.
 218    /// </summary>
 219    /// <typeparam name="TValue">The result value type.</typeparam>
 220    /// <returns>A failed operation result.</returns>
 221    public static OperationResult<TValue> Failure<TValue>()
 222    {
 2223        return new OperationResult<TValue>(NormalizeReasons(null), EmptyWarnings);
 224    }
 225
 226    /// <summary>
 227    /// Creates a failed operation result from this result's reasons and warnings.
 228    /// </summary>
 229    /// <returns>A failed operation result.</returns>
 230    public OperationResult ToFailure()
 231    {
 2232        return Failed
 2233            ? this
 2234            : Failure();
 235    }
 236
 237    /// <summary>
 238    /// Normalizes operation reasons and provides a default failure reason when none are supplied.
 239    /// </summary>
 240    /// <param name="reasons">The reasons to normalize.</param>
 241    /// <returns>A normalized reason collection.</returns>
 242    protected static IReadOnlyList<OperationReason> NormalizeReasons(IEnumerable<OperationReason>? reasons)
 243    {
 13244        return NormalizeReasons(reasons, DefaultFailureCode, DefaultFailureMessage);
 245    }
 246
 247    private static ReadOnlyCollection<OperationReason> NormalizeReasons(
 248        IEnumerable<OperationReason>? reasons,
 249        string fallbackCode,
 250        string fallbackMessage)
 251    {
 13252        if (reasons is null)
 253        {
 3254            return CreateFallbackReason(fallbackCode, fallbackMessage);
 255        }
 256
 10257        if (reasons is ICollection<OperationReason> collection)
 258        {
 8259            if (collection.Count == 0)
 260            {
 2261                return CreateFallbackReason(fallbackCode, fallbackMessage);
 262            }
 263
 6264            var normalizedReasons = new OperationReason[collection.Count];
 6265            int normalizedCount = 0;
 266
 30267            foreach (OperationReason? reason in collection)
 268            {
 9269                if (reason is not null)
 270                {
 7271                    normalizedReasons[normalizedCount] = reason;
 7272                    normalizedCount++;
 273                }
 274            }
 275
 6276            if (normalizedCount == 0)
 277            {
 1278                return CreateFallbackReason(fallbackCode, fallbackMessage);
 279            }
 280
 5281            if (normalizedCount == normalizedReasons.Length)
 282            {
 4283                return Array.AsReadOnly(normalizedReasons);
 284            }
 285
 1286            var filteredReasons = new OperationReason[normalizedCount];
 1287            Array.Copy(normalizedReasons, filteredReasons, normalizedCount);
 288
 1289            return Array.AsReadOnly(filteredReasons);
 290        }
 291
 2292        List<OperationReason>? normalizedList = null;
 293
 8294        foreach (OperationReason? reason in reasons)
 295        {
 2296            if (reason is not null)
 297            {
 2298                normalizedList ??= [];
 2299                normalizedList.Add(reason);
 300            }
 301        }
 302
 2303        return normalizedList is null || normalizedList.Count == 0
 2304            ? CreateFallbackReason(fallbackCode, fallbackMessage)
 2305            : Array.AsReadOnly([.. normalizedList]);
 306    }
 307
 308    private static ReadOnlyCollection<OperationReason> CreateFallbackReason(
 309        string fallbackCode,
 310        string fallbackMessage)
 311    {
 7312        return Array.AsReadOnly([OperationReason.Create(fallbackCode, fallbackMessage)]);
 313    }
 314
 315    /// <summary>
 316    /// Normalizes warning messages.
 317    /// </summary>
 318    /// <param name="warnings">The warnings to normalize.</param>
 319    /// <returns>A normalized warning collection.</returns>
 320    protected static IReadOnlyList<string> NormalizeWarnings(IEnumerable<string>? warnings)
 321    {
 8322        string[] normalizedWarnings = warnings?
 12323            .Where(warning => !string.IsNullOrWhiteSpace(warning))
 9324            .Select(warning => warning.Trim())
 8325            .ToArray() ?? [];
 326
 8327        return normalizedWarnings.Length == 0
 8328            ? EmptyWarnings
 8329            : Array.AsReadOnly(normalizedWarnings);
 330    }
 331
 332    private static ReadOnlyCollection<string> CreateReasonCodes(IReadOnlyList<OperationReason> reasons)
 333    {
 89334        if (reasons.Count == 0)
 335        {
 45336            return EmptyReasonCodes;
 337        }
 338
 44339        string[] reasonCodes = new string[reasons.Count];
 340
 182341        for (int index = 0; index < reasons.Count; index++)
 342        {
 47343            reasonCodes[index] = reasons[index].Code;
 344        }
 345
 44346        return Array.AsReadOnly(reasonCodes);
 347    }
 348}

Methods/Properties

.cctor()
.ctor(System.Boolean,System.Collections.Generic.IReadOnlyList`1<AsiBackbone.Core.Results.OperationReason>,System.Collections.Generic.IReadOnlyList`1<System.String>)
get_Succeeded()
get_Failed()
get_Reasons()
get_ReasonCodes()
get_Warnings()
get_HasWarnings()
Success()
Success(System.Collections.Generic.IEnumerable`1<System.String>)
Success(TValue)
Success(TValue,System.Collections.Generic.IEnumerable`1<System.String>)
Failure(System.String,System.String)
Failure(System.String,System.String)
Failure(AsiBackbone.Core.Results.OperationReason)
Failure(AsiBackbone.Core.Results.OperationReason)
Failure(System.Collections.Generic.IEnumerable`1<AsiBackbone.Core.Results.OperationReason>)
Failure(System.Collections.Generic.IEnumerable`1<AsiBackbone.Core.Results.OperationReason>)
Failure(System.Collections.Generic.IEnumerable`1<AsiBackbone.Core.Results.OperationReason>,System.Collections.Generic.IEnumerable`1<System.String>)
Failure(System.Collections.Generic.IEnumerable`1<AsiBackbone.Core.Results.OperationReason>,System.Collections.Generic.IEnumerable`1<System.String>)
Failure()
Failure()
ToFailure()
NormalizeReasons(System.Collections.Generic.IEnumerable`1<AsiBackbone.Core.Results.OperationReason>)
NormalizeReasons(System.Collections.Generic.IEnumerable`1<AsiBackbone.Core.Results.OperationReason>,System.String,System.String)
CreateFallbackReason(System.String,System.String)
NormalizeWarnings(System.Collections.Generic.IEnumerable`1<System.String>)
CreateReasonCodes(System.Collections.Generic.IReadOnlyList`1<AsiBackbone.Core.Results.OperationReason>)