diff --git a/src/GuardClauses/GuardAgainstExpressionExtensions.cs b/src/GuardClauses/GuardAgainstExpressionExtensions.cs index 7b770d3a..170011c5 100644 --- a/src/GuardClauses/GuardAgainstExpressionExtensions.cs +++ b/src/GuardClauses/GuardAgainstExpressionExtensions.cs @@ -1,15 +1,16 @@ using System; using System.Threading.Tasks; using System.Runtime.CompilerServices; +using System.Threading; namespace Ardalis.GuardClauses; public static partial class GuardClauseExtensions { /// - /// Validates the using the specified and throws an or a custom if it evaluates to true. + /// Validates the using the specified and throws an . /// The should return true to indicate an invalid or undesirable state of the input. - /// If returns true, an or a custom is thrown, signifying that the input is invalid. + /// If returns true, an is thrown, signifying that the input is invalid. /// /// The type of the input parameter. /// The guard clause instance. @@ -17,58 +18,86 @@ public static partial class GuardClauseExtensions /// The input to evaluate. /// The message to include in the exception if the input is invalid. /// The name of the parameter to include in the thrown exception, captured automatically from the input expression. - /// /// The if the evaluates to false, indicating a valid state. /// Thrown when the validation function returns true, indicating that the input is invalid. - /// public static T Expression(this IGuardClause guardClause, Func func, T input, string message, - [CallerArgumentExpression("input")] string? parameterName = null, - Func? exceptionCreator = null) + [CallerArgumentExpression(nameof(input))] string? parameterName = null) where T : struct { - if (func(input)) - { - Exception? exception = exceptionCreator?.Invoke(); - - throw exception ?? new ArgumentException(message, parameterName!); - } + return guardClause.Expression(func, input, () => new ArgumentException(message, parameterName!)); + } - return input; + /// + /// Validates the using the specified and throws a custom if it evaluates to true. + /// The should return true to indicate an invalid or undesirable state of the input. + /// If returns true, a custom is thrown, signifying that the input is invalid. + /// + /// The type of the input parameter. + /// The guard clause instance. + /// The function that evaluates the input. It should return true if the input is considered invalid or in a negative state. + /// The input to evaluate. + /// A factory method to create the custom exception. + /// The if the evaluates to false, indicating a valid state. + /// + public static T Expression(this IGuardClause guardClause, + Func func, + T input, + Func createException) + where T : struct + { + return func(input) ? throw createException() : input; } /// - /// Validates the asynchronously and throws an or a custom if it evaluates to false for given + /// Validates the asynchronously and throws an if it evaluates to false for given /// The should return true to indicate an invalid or undesirable state. - /// If returns true, indicating that the input is invalid, an or a custom is thrown. + /// If returns true, indicating that the input is invalid, an is thrown. /// /// The type of the input parameter. - /// The function that evaluates the input. It should return true if the input is considered invalid or in a negative state. /// The guard clause instance. + /// The function that evaluates the input. It should return true if the input is considered invalid or in a negative state. /// The input to evaluate. /// The message to include in the exception if the input is invalid. + /// A to observe while waiting for the task to complete. /// The name of the parameter to include in the thrown exception, captured automatically from the input expression. - /// /// if the evaluates to true /// Thrown when the validation function returns true, indicating that the input is invalid. - /// - public static async Task ExpressionAsync(this IGuardClause guardClause, - Func> func, + public static Task ExpressionAsync(this IGuardClause guardClause, + Func> func, T input, string message, - [CallerArgumentExpression("input")] string? parameterName = null, - Func? exceptionCreator = null) + CancellationToken cancellationToken = default, + [CallerArgumentExpression(nameof(input))] string? parameterName = null) where T : struct { - if (await func(input)) - { - Exception? exception = exceptionCreator?.Invoke(); - - throw exception ?? new ArgumentException(message, parameterName!); - } + return guardClause.ExpressionAsync(func, input, () => new ArgumentException(message, parameterName!), cancellationToken); + } - return input; + /// + /// Validates the asynchronously and throws a custom if it evaluates to false for given + /// The should return true to indicate an invalid or undesirable state. + /// If returns true, indicating that the input is invalid, a custom is thrown. + /// + /// The type of the input parameter. + /// The guard clause instance. + /// The function that evaluates the input. It should return true if the input is considered invalid or in a negative state. + /// The input to evaluate. + /// A factory method to create the custom exception. + /// A to observe while waiting for the task to complete. + /// if the evaluates to true + /// Thrown when the validation function returns true, indicating that the input is invalid. + /// + public static async Task ExpressionAsync( + this IGuardClause guardClause, + Func> func, + T input, + Func createException, + CancellationToken cancellationToken = default) + where T : struct + { + return await func(input, cancellationToken).ConfigureAwait(false) ? throw createException() : input; } } diff --git a/test/GuardClauses.UnitTests/GuardAgainstExpression.cs b/test/GuardClauses.UnitTests/GuardAgainstExpression.cs index 4c9c51c7..ca71790f 100644 --- a/test/GuardClauses.UnitTests/GuardAgainstExpression.cs +++ b/test/GuardClauses.UnitTests/GuardAgainstExpression.cs @@ -26,7 +26,7 @@ public static IEnumerable GetCustomStruct() public void GivenIntegerWhenTheExpressionEvaluatesToTrueThrowsException() { int testCase = 10; - Assert.Throws(() => Guard.Against.Expression((x) => x == 10, testCase, "Value cannot be 10")); + Assert.Throws(() => Guard.Against.Expression(x => x == 10, testCase, "Value cannot be 10")); } [Fact] @@ -34,7 +34,7 @@ public void GivenIntegerWhenTheExpressionEvaluatesToTrueThrowsCustomExceptionWhe { Exception customException = new Exception(); int testCase = 10; - Assert.Throws(() => Guard.Against.Expression((x) => x == 10, testCase, "Value cannot be 10", exceptionCreator: () => customException)); + Assert.Throws(() => Guard.Against.Expression(x => x == 10, testCase, () => customException)); } @@ -42,14 +42,14 @@ public void GivenIntegerWhenTheExpressionEvaluatesToTrueThrowsCustomExceptionWhe public void GivenIntegerWhenTheExpressionEvaluatesToFalseDoesNothing() { int testCase = 10; - Guard.Against.Expression((x) => x == 5, testCase, "Value cannot be 5"); + Guard.Against.Expression(x => x == 5, testCase, "Value cannot be 5"); } [Fact] public void GivenDoubleWhenTheExpressionEvaluatesToTrueThrowsException() { double testCase = 1.1; - Assert.Throws(() => Guard.Against.Expression((x) => x == 1.1, testCase, "Value cannot be 1.1")); + Assert.Throws(() => Guard.Against.Expression(x => x == 1.1, testCase, "Value cannot be 1.1")); } [Fact] @@ -57,7 +57,7 @@ public void GivenDoubleWhenTheExpressionEvaluatesToTrueThrowsCustomExceptionWhen { Exception customException = new Exception(); double testCase = 1.1; - Assert.Throws(() => Guard.Against.Expression((x) => x == 1.1, testCase, "Value cannot be 1.1", exceptionCreator: () => customException)); + Assert.Throws(() => Guard.Against.Expression(x => x == 1.1, testCase, () => customException)); } @@ -65,14 +65,14 @@ public void GivenDoubleWhenTheExpressionEvaluatesToTrueThrowsCustomExceptionWhen public void GivenDoubleWhenTheExpressionEvaluatesToFalseDoesNothing() { double testCase = 1.1; - Guard.Against.Expression((x) => x == 5.0, testCase, "Value cannot be 5.0"); + Guard.Against.Expression(x => x == 5.0, testCase, "Value cannot be 5.0"); } [Theory] [MemberData(nameof(GetCustomStruct))] public void GivenCustomStructWhenTheExpressionEvaluatesToTrueThrowsException(CustomStruct test) { - Assert.Throws(() => Guard.Against.Expression((x) => x.FieldName == "FieldValue", test, "FieldValue is not matching")); + Assert.Throws(() => Guard.Against.Expression(x => x.FieldName == "FieldValue", test, "FieldValue is not matching")); } [Theory] @@ -80,7 +80,7 @@ public void GivenCustomStructWhenTheExpressionEvaluatesToTrueThrowsException(Cus public void GivenCustomStructWhenTheExpressionEvaluatesToTrueThrowsCustomExceptionWhenSupplied(CustomStruct test) { Exception customException = new Exception(); - Assert.Throws(() => Guard.Against.Expression((x) => x.FieldName == "FieldValue", test, "FieldValue is not matching", exceptionCreator: () => customException)); + Assert.Throws(() => Guard.Against.Expression(x => x.FieldName == "FieldValue", test, () => customException)); } @@ -88,7 +88,7 @@ public void GivenCustomStructWhenTheExpressionEvaluatesToTrueThrowsCustomExcepti [MemberData(nameof(GetCustomStruct))] public void GivenCustomStructWhenTheExpressionEvaluatesToFalseDoesNothing(CustomStruct test) { - Guard.Against.Expression((x) => x.FieldName == "FailThis", test, "FieldValue is not matching"); + Guard.Against.Expression(x => x.FieldName == "FailThis", test, "FieldValue is not matching"); } [Fact]