/// <summary> /// Ensures that the collection contains at most the number of specified items /// </summary> /// <param name="collection"> /// The collection to be validated. /// </param> /// <param name="minNumberOfItems"> /// The maximum number of items that the collection must have /// </param> /// <param name="argumentName"> /// The argument name. /// </param> /// <exception cref="System.ArgumentNullException"> /// If the collection itself is null /// </exception> /// <exception cref="System.ArgumentException"> /// If the collection contains more than the minumum number of items. OR. the maxNumberOfItems /// argument is less than zero. /// </exception> public static void ContainsAtMost <T>(IEnumerable <T> collection, int maxNumberOfItems, string argumentName, string message) { Insist.IsNotNull(collection, "collection"); Insist.IsAtLeast(maxNumberOfItems, 0, "maxNumberOfItems"); if (CountItems(collection) > maxNumberOfItems) { throw new ArgumentException( message ?? "collection contains more than the maximum number of items", argumentName ?? "collection"); } }
/// <summary> /// Attempt to execute the supplied function. /// </summary> /// <param name="numberOfAttempts"> /// The number of attempts to try /// </param> /// <param name="interval"> /// The amount of time to wait inbetween attempts /// </param> /// <param name="functionToAttempt"> /// The function to try and execute /// </param> /// <param name="handleExceptions"> /// Whether or not to handle exceptions that get thrown as part of /// executing the supplied function. /// </param> /// <returns> /// An OperationResult that denotes whether or not the function succeeded. /// If the function succeeded then OperationResult.Succeeded is returned. /// If the function failed then a failure OperationResult is returned with /// details of the failuer and any thrown exceptions (if handleExceptions was true) /// </returns> /// <exception cref="System.ArgumentException"> /// Thrown if /// numberOfAttempts is less than 1 /// interval is less than 1 millisecond /// </exception> /// <exception cref="System.ArgumentNullException"> /// Thrown if /// functionToAttempt is null /// </exception> public static OperationResult Attempt( Func <bool> functionToAttempt, int numberOfAttempts, TimeSpan interval, RetryExceptionBehaviour exceptionBehaviour) { #region Input validation Insist.IsAtLeast(numberOfAttempts, 1, "numberOfAttempts"); Insist.IsAtLeast(interval, TimeSpan.FromMilliseconds(1), "interval"); Insist.IsNotNull(functionToAttempt, "functionToAttempt"); Insist.IsDefined <RetryExceptionBehaviour>(exceptionBehaviour, "exceptionBehaviour"); #endregion int currentAttempts = 0; List <Exception> thrownExceptions = new List <Exception>(); int numberOfThrownExceptions = 0; bool usingInfiniteAttempts = numberOfAttempts == INFINITE_ATTEMPTS; while (currentAttempts < numberOfAttempts) { bool success = false; try { success = functionToAttempt(); } catch (Exception e) { if (exceptionBehaviour == RetryExceptionBehaviour.DoNotHandle) { throw; } else if (exceptionBehaviour == RetryExceptionBehaviour.HandleAndCollate) { //Record the exception so that we can return information //about it later on. thrownExceptions.Add(e); numberOfThrownExceptions++; } else if (exceptionBehaviour == RetryExceptionBehaviour.HandleOnly) { numberOfThrownExceptions++; } else { throw new InvalidOperationException(string.Format("Unknown RetryExceptionBehaviour '{0}'", exceptionBehaviour)); } } if (success) { return(OperationResult.Succeeded); } if (!usingInfiniteAttempts) //If we're using an infinite number of attempts then //we don't want to make any progress regards number of //attempts. Just keep looping until the attempt succeeds. { currentAttempts++; } Thread.Sleep(interval); } //If we get to this point then all attempts have failed. List <string> errorMessages = new List <string>(); errorMessages.Add(string.Format("The function was not successfull after {0} attempts", numberOfAttempts)); if (numberOfThrownExceptions > 0) { if (exceptionBehaviour == RetryExceptionBehaviour.HandleAndCollate) { errorMessages.AddRange(thrownExceptions.Select(ex => ex.AllMessages())); } else if (exceptionBehaviour == RetryExceptionBehaviour.HandleOnly) { errorMessages.Add(string.Format(string.Format("A total of '{0}' exceptions were thrown during the attempt", numberOfThrownExceptions))); } } return(new OperationResult(errorMessages)); }
/// <summary> /// Validates an integral argument, throwing ArgumentException if it is less than the acceptable /// minimum value. /// </summary> /// <param name="value">The value to be validated.</param> /// <param name="argumentName">The argument name.</param> /// <param name="minValue">The minimum accepted value.</param> public static void IsAtLeast <T>(T value, T minValue, string argumentName) where T : IComparable <T> { Insist.IsAtLeast(value, minValue, argumentName, null); }