dolittle/DotNET.SDK

View on GitHub
Source/Async/TaskExtensions.cs

Summary

Maintainability
A
0 mins
Test Coverage
F
0%
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;

namespace Dolittle.SDK.Async;

/// <summary>
/// Extension methods for <see cref="Task" />.
/// </summary>
public static class TaskExtensions
{
    /// <summary>
    /// Tries to perform a task that returns a <typeparamref name="T">result</typeparamref>.
    /// </summary>
    /// <typeparam name="T">The <see cref="Type" /> of the result of the <see cref="Task{TResult}" />.</typeparam>
    /// <param name="performTask">The callback that performs the task.</param>
    /// <returns>A <see cref="Task{TResult}" /> that, when resolved returns <see cref="Try{TResult}" />.</returns>
    public static Task<Try<T>> TryTask<T>(this Func<Task<T>> performTask)
        => TryTask(performTask());

    /// <summary>
    /// Tries to perform a task that returns a <typeparamref name="T">result</typeparamref>.
    /// </summary>
    /// <typeparam name="T">The <see cref="Type" /> of the result of the <see cref="Task{TResult}" />.</typeparam>
    /// <param name="task">The task.</param>
    /// <returns>A <see cref="Task{TResult}" /> that, when resolved returns <see cref="Try{TResult}" />.</returns>
    public static async Task<Try<T>> TryTask<T>(this Task<T> task)
    {
        try
        {
            return await task.ConfigureAwait(false);
        }
        catch (Exception ex)
        {
            return ex;
        }
    }

    /// <summary>
    /// Tries to perform a task.
    /// </summary>
    /// <param name="performTask">The callback that performs the task.</param>
    /// <returns>A <see cref="Task{TResult}" /> that, when resolved returns <see cref="Try{TResult}" />.</returns>
    public static Task<Try> TryTask(this Func<Task> performTask)
        => TryTask(performTask());

    /// <summary>
    /// Tries to perform a task.
    /// </summary>
    /// <param name="task">The task.</param>
    /// <returns>A <see cref="Task{TResult}" /> that, when resolved returns <see cref="Try{TResult}" />.</returns>
    public static async Task<Try> TryTask(this Task task)
    {
        try
        {
            await task.ConfigureAwait(false);
            return new Try();
        }
        catch (Exception ex)
        {
            return ex;
        }
    }

    /// <summary>
    /// Try get the <see cref="Exception" /> from a <see cref="Task" />.
    /// </summary>
    /// <param name="task">The <see cref="Task" />.</param>
    /// <param name="exception">The <see cref="Exception" />.</param>
    /// <returns>A value indicating whether the <see cref="Task" /> had an <see cref="Exception" />.</returns>
    public static bool TryGetException(this Task task, [NotNullWhen(true)] out Exception? exception)
    {
        exception = task.Exception;
        return exception != null;
    }

    /// <summary>
    /// Try get the innermost <see cref="Exception" /> from a <see cref="Task" />.
    /// </summary>
    /// <param name="task">The <see cref="Task" />.</param>
    /// <param name="exception">The <see cref="Exception" />.</param>
    /// <returns>A value indicating whether the <see cref="Task" /> had an <see cref="Exception" />.</returns>
    public static bool TryGetInnerMostException(this Task task, [NotNullWhen(true)] out Exception? exception)
    {
        var hasException = task.TryGetException(out exception);
        while (exception?.InnerException != null) exception = exception.InnerException;
        return hasException;
    }
}