diff --git a/src/Common/IValidatable.cs b/src/Common/IValidatable.cs new file mode 100644 index 0000000..a2c05fc --- /dev/null +++ b/src/Common/IValidatable.cs @@ -0,0 +1,25 @@ +namespace Throw; + +/// +/// asdf. +/// +/// asdf. +public interface IValidatable +{ + /// + /// asdf. + /// + /// + T Value { get; } + + /// + /// asdf. + /// + /// + string ParamName { get; } + + /// + /// asdf. + /// + ExceptionCustomizations? ExceptionCustomizations { get; } +} \ No newline at end of file diff --git a/src/Common/Validatable.cs b/src/Common/Validatable.cs index 198dcb6..041543c 100644 --- a/src/Common/Validatable.cs +++ b/src/Common/Validatable.cs @@ -7,7 +7,9 @@ namespace Throw; /// The value to be validated. /// The name of the parameter holding the . /// Customizations to the exception, which will be applied if an exception is thrown. -public readonly record struct Validatable(TValue Value, string ParamName, ExceptionCustomizations? ExceptionCustomizations = null) where TValue : notnull +public readonly record struct Validatable(TValue Value, string ParamName, ExceptionCustomizations? ExceptionCustomizations = null) + : IValidatable + where TValue : notnull { /// /// Implicit conversion operator back to the original value's type. diff --git a/src/Program.cs b/src/Program.cs new file mode 100644 index 0000000..1f188b4 --- /dev/null +++ b/src/Program.cs @@ -0,0 +1,9 @@ +using Throw; + +int[] collection = new[] { 1, 2, 3 }; +var collection2 = Enumerable.Range(0, 10); +List collection3 = collection2.ToList(); + +collection.Throw().IfAny(x => x > 2); +collection2.Throw().IfAny(x => x > 2); +collection3.Throw().IfAny(x => x > 2); \ No newline at end of file diff --git a/src/Throw.csproj b/src/Throw.csproj index ae909e0..d6d102c 100644 --- a/src/Throw.csproj +++ b/src/Throw.csproj @@ -6,6 +6,7 @@ enable true true + Exe diff --git a/src/ValidatableExtensions/ValidatableExtensions.Collections.cs b/src/ValidatableExtensions/ValidatableExtensions.Collections.cs index 6824241..3b24371 100644 --- a/src/ValidatableExtensions/ValidatableExtensions.Collections.cs +++ b/src/ValidatableExtensions/ValidatableExtensions.Collections.cs @@ -118,4 +118,19 @@ public static ref readonly Validatable IfHasNullElements(this in return ref validatable; } + + /// + /// Throws an exception if any of the items in the collection matches the . + /// Important note: if the collection is a non-evaluated expression, the expression will be evaluated. + /// + /// + /// The default exception thrown is an . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static IValidatable> IfAny(this IValidatable> validatable, Func predicate, [CallerArgumentExpression("predicate")] string? predicateName = null) + { + Validator.ThrowIfAny(validatable.Value, predicate, predicateName!, validatable.ParamName, validatable.ExceptionCustomizations); + + return validatable; + } } \ No newline at end of file diff --git a/src/Validators/Validator.Collections.cs b/src/Validators/Validator.Collections.cs index 4650cf2..4fac90e 100644 --- a/src/Validators/Validator.Collections.cs +++ b/src/Validators/Validator.Collections.cs @@ -57,6 +57,19 @@ internal static void ThrowIfHasNullElements(TValue value, string paramNa } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ThrowIfAny(TValue value, Func predicate, string predicateName, string paramName, ExceptionCustomizations? exceptionCustomizations) + where TValue : notnull, IEnumerable + { + foreach (var item in value) + { + if (predicate(item)) + { + ExceptionThrower.Throw(paramName, exceptionCustomizations, $"Collection should not have any elements matching {predicateName}."); + } + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int GetCollectionCount(TValue value) where TValue : notnull, IEnumerable