Esempio n. 1
0
        /// <summary>
        /// Applies a function to a series of Result arguments
        /// </summary>
        /// <typeparam name="TFailure">Type of Failure</typeparam>
        /// <typeparam name="TResult">Type of Success</typeparam>
        /// <typeparam name="T1">Type of the first argument</typeparam>
        /// <typeparam name="T2">Type of the second argument</typeparam>
        /// <typeparam name="T3">Type of the third argument</typeparam>
        /// <param name="func">Function to call</param>
        /// <param name="first">First argument for the function</param>
        /// <param name="second">Second argument for the function</param>
        /// <param name="third">Third argument for the function</param>
        /// <returns>If all arguments are Success, then a Success is returned. Otherwise, all the Failures are concatentated into a Failure Result</returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static IResult <IEnumerable <TFailure>, TResult> Apply <TResult, TFailure, T1, T2, T3>(Func <T1, T2, T3, TResult> func, IResult <TFailure, T1> first, IResult <TFailure, T2> second, IResult <TFailure, T3> third)
        {
            if (func == null)
            {
                throw new ArgumentNullException(nameof(func));
            }
            if (first == null)
            {
                throw new ArgumentNullException(nameof(first));
            }
            if (second == null)
            {
                throw new ArgumentNullException(nameof(second));
            }
            if (third == null)
            {
                throw new ArgumentNullException(nameof(third));
            }


            IResult <IEnumerable <TFailure>, TResult> doSuccess()
            {
                var firstValue  = ((Success <TFailure, T1>)first).Value;
                var secondValue = ((Success <TFailure, T2>)second).Value;
                var thirdValue  = ((Success <TFailure, T3>)third).Value;

                return(Success <IEnumerable <TFailure>, TResult>(func(firstValue, secondValue, thirdValue)));
            }

            IResult <IEnumerable <TFailure>, TResult> doFailure()
            {
                var errors = new List <TFailure>();

                void addError(TFailure error) => errors.Add(error);

                first.Do(addError, _ => { });
                second.Do(addError, _ => { });
                third.Do(addError, _ => { });
                return(Failure <IEnumerable <TFailure>, TResult>(errors));
            }

            var firstIsSuccess  = first is Success <TFailure, T1>;
            var secondIsSuccess = second is Success <TFailure, T2>;
            var thirdIsSuccess  = third is Success <TFailure, T3>;

            return(firstIsSuccess && secondIsSuccess && thirdIsSuccess?doSuccess() : doFailure());
        }