Skip to content

Commit

Permalink
Added new "exception" optional parameter (#344)
Browse files Browse the repository at this point in the history
* Added New Optional Parameter : customException

A custom exception can be supplied to the guard clause methods to throw it instead of the default exception

* Added new "exception" optional parameter

A custom exception can be supplied to the guard clause methods to throw it instead of the default exception

* renamed customException to just exception

* Added Unit Tests for optional Custom Exception parameter

Also fixed a few named arguments missing from method calls that i found through running the tests
  • Loading branch information
UnleashedGH authored Apr 19, 2024
1 parent 04f0487 commit b4771e5
Show file tree
Hide file tree
Showing 46 changed files with 1,036 additions and 195 deletions.
18 changes: 12 additions & 6 deletions src/GuardClauses/GuardAgainstEmptyOrWhiteSpaceExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,49 @@ public static partial class GuardClauseExtensions
{
#if NET5_0_OR_GREATER
/// <summary>
/// Throws an <see cref="ArgumentException" /> if <paramref name="input" /> is an empty string.
/// Throws an <see cref="ArgumentException" /> or a custom <see cref="Exception" /> if <paramref name="input" /> is an empty string.
/// </summary>
/// <param name="guardClause"></param>
/// <param name="input"></param>
/// <param name="parameterName"></param>
/// <param name="message">Optional. Custom error message</param>
/// <param name="exception">Optional. Custom exception</param>
/// <returns><paramref name="input" /> if the value is not an empty string.</returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="Exception"></exception>

public static ReadOnlySpan<char> Empty(this IGuardClause guardClause,
ReadOnlySpan<char> input,
string parameterName,
string? message = null)
string? message = null,
Exception? exception = null)
{
if (input.Length == 0 || input == string.Empty)
{
throw new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName);
throw exception ?? new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName);
}
return input;
}

/// <summary>
/// Throws an <see cref="ArgumentException" /> if <paramref name="input" /> is an empty or white space string.
/// Throws an <see cref="ArgumentException" /> or a custom <see cref="Exception" /> if <paramref name="input" /> is an empty or white space string.
/// </summary>
/// <param name="guardClause"></param>
/// <param name="input"></param>
/// <param name="parameterName"></param>
/// <param name="message">Optional. Custom error message</param>
/// <param name="exception">Optional. Custom exception</param>
/// <returns><paramref name="input" /> if the value is not an empty or whitespace string.</returns>
/// <exception cref="ArgumentException"></exception>
public static ReadOnlySpan<char> WhiteSpace(this IGuardClause guardClause,
ReadOnlySpan<char> input,
string parameterName,
string? message = null)
string? message = null,
Exception? exception = null)
{
if (MemoryExtensions.IsWhiteSpace(input))
{
throw new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName);
throw exception ?? new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName!);
}

return input;
Expand Down
22 changes: 14 additions & 8 deletions src/GuardClauses/GuardAgainstExpressionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,62 @@ namespace Ardalis.GuardClauses;
public static partial class GuardClauseExtensions
{
/// <summary>
/// Validates the <paramref name="input"/> using the specified <paramref name="func"/> and throws an <see cref="ArgumentException"/> if it evaluates to true.
/// Validates the <paramref name="input"/> using the specified <paramref name="func"/> and throws an <see cref="ArgumentException"/> or a custom <see cref="Exception" /> if it evaluates to true.
/// The <paramref name="func"/> should return true to indicate an invalid or undesirable state of the input.
/// If <paramref name="func"/> returns true, an <see cref="ArgumentException"/> is thrown, signifying that the input is invalid.
/// If <paramref name="func"/> returns true, an <see cref="ArgumentException"/> or a custom <see cref="Exception" /> is thrown, signifying that the input is invalid.
/// </summary>
/// <typeparam name="T">The type of the input parameter.</typeparam>
/// <param name="guardClause">The guard clause instance.</param>
/// <param name="func">The function that evaluates the input. It should return true if the input is considered invalid or in a negative state.</param>
/// <param name="input">The input to evaluate.</param>
/// <param name="message">The message to include in the exception if the input is invalid.</param>
/// <param name="parameterName">The name of the parameter to include in the thrown exception, captured automatically from the input expression.</param>
/// <param name="exception"></param>
/// <returns>The <paramref name="input"/> if the <paramref name="func"/> evaluates to false, indicating a valid state.</returns>
/// <exception cref="ArgumentException">Thrown when the validation function returns true, indicating that the input is invalid.</exception>
/// <exception cref="Exception"></exception>
public static T Expression<T>(this IGuardClause guardClause,
Func<T, bool> func,
T input,
string message,
[CallerArgumentExpression("input")] string? parameterName = null)
[CallerArgumentExpression("input")] string? parameterName = null,
Exception? exception = null)
where T : struct
{
if (func(input))
{
throw new ArgumentException(message, parameterName!);
throw exception ?? new ArgumentException(message, parameterName!);
}

return input;
}

/// <summary>
/// Validates the <paramref name="func"/> asynchronously and throws an <see cref="ArgumentException" /> if it evaluates to false for given <paramref name="input"/>
/// Validates the <paramref name="func"/> asynchronously and throws an <see cref="ArgumentException" /> or a custom <see cref="Exception" /> if it evaluates to false for given <paramref name="input"/>
/// The <paramref name="func"/> should return true to indicate an invalid or undesirable state.
/// If <paramref name="func"/> returns true, indicating that the input is invalid, an <see cref="ArgumentException"/> is thrown.
/// If <paramref name="func"/> returns true, indicating that the input is invalid, an <see cref="ArgumentException"/> or a custom <see cref="Exception" /> is thrown.
/// </summary>
/// <typeparam name="T">The type of the input parameter.</typeparam>
/// <param name="func">The function that evaluates the input. It should return true if the input is considered invalid or in a negative state.</param>
/// <param name="guardClause">The guard clause instance.</param>
/// <param name="input">The input to evaluate.</param>
/// <param name="message">The message to include in the exception if the input is invalid.</param>
/// <param name="parameterName">The name of the parameter to include in the thrown exception, captured automatically from the input expression.</param>
/// <param name="exception"></param>
/// <returns><paramref name="input"/> if the <paramref name="func"/> evaluates to true </returns>
/// <exception cref="ArgumentException">Thrown when the validation function returns true, indicating that the input is invalid.</exception>
/// <exception cref="Exception"></exception>
public static async Task<T> ExpressionAsync<T>(this IGuardClause guardClause,
Func<T, Task<bool>> func,
T input,
string message,
[CallerArgumentExpression("input")] string? parameterName = null)
[CallerArgumentExpression("input")] string? parameterName = null,
Exception? exception = null)
where T : struct
{
if (await func(input))
{
throw new ArgumentException(message, parameterName!);
throw exception ?? new ArgumentException(message, parameterName!);
}

return input;
Expand Down
30 changes: 21 additions & 9 deletions src/GuardClauses/GuardAgainstInvalidFormatExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,71 +7,83 @@ namespace Ardalis.GuardClauses;
public static partial class GuardClauseExtensions
{
/// <summary>
/// Throws an <see cref="ArgumentException" /> if <paramref name="input"/> doesn't match the <paramref name="regexPattern"/>.
/// Throws an <see cref="ArgumentException" /> or a custom <see cref="Exception" /> if <paramref name="input"/> doesn't match the <paramref name="regexPattern"/>.
/// </summary>
/// <param name="guardClause"></param>
/// <param name="input"></param>
/// <param name="parameterName"></param>
/// <param name="regexPattern"></param>
/// <param name="message">Optional. Custom error message</param>
/// <param name="exception"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="Exception"></exception>
public static string InvalidFormat(this IGuardClause guardClause,
string input,
string parameterName,
string regexPattern,
string? message = null)
string? message = null,
Exception? exception = null)
{
var m = Regex.Match(input, regexPattern);
if (!m.Success || input != m.Value)
{
throw new ArgumentException(message ?? $"Input {parameterName} was not in required format", parameterName);
throw exception ?? new ArgumentException(message ?? $"Input {parameterName} was not in required format", parameterName);
}

return input;
}

/// <summary>
/// Throws an <see cref="ArgumentException" /> if <paramref name="input"/> doesn't satisfy the <paramref name="predicate"/> function.
/// Throws an <see cref="ArgumentException" /> or a custom <see cref="Exception" /> if <paramref name="input"/> doesn't satisfy the <paramref name="predicate"/> function.
/// </summary>
/// <param name="guardClause"></param>
/// <param name="input"></param>
/// <param name="parameterName"></param>
/// <param name="predicate"></param>
/// <param name="message">Optional. Custom error message</param>
/// <param name="exception"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static T InvalidInput<T>(this IGuardClause guardClause, T input, string parameterName, Func<T, bool> predicate, string? message = null)
/// <exception cref="Exception"></exception>
public static T InvalidInput<T>(this IGuardClause guardClause,
T input, string parameterName,
Func<T, bool> predicate,
string? message = null,
Exception? exception = null)
{
if (!predicate(input))
{
throw new ArgumentException(message ?? $"Input {parameterName} did not satisfy the options", parameterName);
throw exception ?? new ArgumentException(message ?? $"Input {parameterName} did not satisfy the options", parameterName);
}

return input;
}

/// <summary>
/// Throws an <see cref="ArgumentException" /> if <paramref name="input"/> doesn't satisfy the <paramref name="predicate"/> function.
/// Throws an <see cref="ArgumentException" /> or a custom <see cref="Exception" /> if <paramref name="input"/> doesn't satisfy the <paramref name="predicate"/> function.
/// </summary>
/// <param name="guardClause"></param>
/// <param name="input"></param>
/// <param name="parameterName"></param>
/// <param name="predicate"></param>
/// <param name="message">Optional. Custom error message</param>
/// <param name="exception"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="Exception"></exception>
public static async Task<T> InvalidInputAsync<T>(this IGuardClause guardClause,
T input,
string parameterName,
Func<T, Task<bool>> predicate,
string? message = null)
string? message = null,
Exception? exception = null)
{
if (!await predicate(input))
{
throw new ArgumentException(message ?? $"Input {parameterName} did not satisfy the options", parameterName);
throw exception ?? new ArgumentException(message ?? $"Input {parameterName} did not satisfy the options", parameterName);
}

return input;
Expand Down
Loading

0 comments on commit b4771e5

Please sign in to comment.