Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections;
using System.Linq.Expressions;

namespace Throw;

Expand Down Expand Up @@ -231,4 +232,90 @@ public static ref readonly Validatable<TValue> IfNotContains<TValue, TElement, T

return ref validatable;
}

/// <summary>
/// Throws an exception if the collection returned from the given <paramref name="func"/> contains the specified element <paramref name="func"/>.
/// Important note: if the collection is a non-evaluated expression, the expression will be evaluated.
/// </summary>
/// <remarks>
/// The default exception thrown is an <see cref="ArgumentException"/>.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref readonly Validatable<TValue> IfAny<TValue, TCollectionType>(this in Validatable<TValue> validatable, Func<TValue, TCollectionType> func, Expression<Func<TValue, bool>> predicate, [CallerArgumentExpression("func")] string? funcName = null)
where TValue : notnull
where TCollectionType : IEnumerable
{

Validator.ThrowIfContainsElement(func(validatable.Value), predicate,$"{validatable.ParamName}: {funcName}", validatable.ExceptionCustomizations);

return ref validatable;
}

/// <summary>
/// Throws an exception if the collection returned from the given <paramref name="func"/> contains exactly one occurence of the specified element <paramref name="element"/>.
/// Important note: if the collection is a non-evaluated expression, the expression will be evaluated.
/// </summary>
/// <remarks>
/// The default exception thrown is an <see cref="ArgumentException"/>.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref readonly Validatable<TValue> IfSingle<TValue, TCollectionType>(this in Validatable<TValue> validatable, Func<TValue, TCollectionType> func, dynamic element, [CallerArgumentExpression("func")] string? funcName = null)
where TValue : notnull
where TCollectionType : IEnumerable
{
Validator.ThrowIfContainsSingleElement(func(validatable.Value), element, $"{validatable.ParamName}: {funcName}", validatable.ExceptionCustomizations);

return ref validatable;
}

/// <summary>
/// Throws an exception if the collection returned from the given <paramref name="func"/> contains multiple occurence of the specified element <paramref name="element"/>.
/// Important note: if the collection is a non-evaluated expression, the expression will be evaluated.
/// </summary>
/// <remarks>
/// The default exception thrown is an <see cref="ArgumentException"/>.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref readonly Validatable<TValue> IfNotSingle<TValue, TCollectionType>(this in Validatable<TValue> validatable, Func<TValue, TCollectionType> func, dynamic element, [CallerArgumentExpression("func")] string? funcName = null)
where TValue : notnull
where TCollectionType : IEnumerable
{
Validator.ThrowIfContainsNoSingleElement(func(validatable.Value), element, $"{validatable.ParamName}: {funcName}", validatable.ExceptionCustomizations);

return ref validatable;
}

/// <summary>
/// Throws an exception if the collection returned from the given <paramref name="func"/> contains no occurence of the specified element <paramref name="element"/>.
/// Important note: if the collection is a non-evaluated expression, the expression will be evaluated.
/// </summary>
/// <remarks>
/// The default exception thrown is an <see cref="ArgumentException"/>.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref readonly Validatable<TValue> IfNone<TValue, TCollectionType>(this in Validatable<TValue> validatable, Func<TValue, TCollectionType> func, dynamic element, [CallerArgumentExpression("func")] string? funcName = null)
where TValue : notnull
where TCollectionType : IEnumerable
{
Validator.ThrowIfContainsNone(func(validatable.Value), element, $"{validatable.ParamName}: {funcName}", validatable.ExceptionCustomizations);

return ref validatable;
}

/// <summary>
/// Throws an exception if the collection returned from the given <paramref name="func"/> has all items matching the specified element <paramref name="element"/>.
/// Important note: if the collection is a non-evaluated expression, the expression will be evaluated.
/// </summary>
/// <remarks>
/// The default exception thrown is an <see cref="ArgumentException"/>.
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref readonly Validatable<TValue> IfAll<TValue, TCollectionType>(this in Validatable<TValue> validatable, Func<TValue, TCollectionType> func, dynamic element, [CallerArgumentExpression("func")] string? funcName = null)
where TValue : notnull
where TCollectionType : IEnumerable
{
Validator.ThrowIfAll(func(validatable.Value), element, $"{validatable.ParamName}: {funcName}", validatable.ExceptionCustomizations);

return ref validatable;
}
}
80 changes: 80 additions & 0 deletions src/Validators/Validator.Collections.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace Throw;

using System.Collections;
using System.Linq.Expressions;

internal static partial class Validator
{
Expand Down Expand Up @@ -152,4 +153,83 @@ static int GetEnumeratedCount(IEnumerable enumerable)
_ => GetEnumeratedCount(value)
};
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void ThrowIfContainsElement<TValue>(TValue value, Expression<Func<TValue, bool>> predicate, string paramName, ExceptionCustomizations? exceptionCustomizations)
where TValue : notnull, IEnumerable
{
foreach (var item in value)
{
if (item)
{
ExceptionThrower.Throw(paramName, exceptionCustomizations, $"Collection should not contain element {element}.");
}
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void ThrowIfContainsSingleElement<TValue>(TValue value, dynamic element, string paramName, ExceptionCustomizations? exceptionCustomizations)
where TValue : notnull, IEnumerable
{
var count = 0;
foreach (var item in value)
{
if (item == element)
{
count++;
if (count > 1) break;
}
}
if (count == 1) ExceptionThrower.Throw(paramName, exceptionCustomizations, $"Collection should not contain a single element having value of {element}.");
}


[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void ThrowIfContainsNoSingleElement<TValue>(TValue value, dynamic element, string paramName, ExceptionCustomizations? exceptionCustomizations)
where TValue : notnull, IEnumerable
{
var count = 0;
foreach (var item in value)
{
if (item == element)
{
count++;
if (count > 1) break;
}
}
if (count > 1) ExceptionThrower.Throw(paramName, exceptionCustomizations, $"Collection should not contain multiple occurences of element having value of {element}.");
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void ThrowIfContainsNone<TValue>(TValue value, dynamic element, string paramName, ExceptionCustomizations? exceptionCustomizations)
where TValue : notnull, IEnumerable
{
var count = 0;
foreach (var item in value)
{
if (item == element)
{
count++;
if (count > 0) break;
}
}
if (count > 0) ExceptionThrower.Throw(paramName, exceptionCustomizations, $"Collection should contain at least one occurences of element having value of {element}.");
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void ThrowIfAll<TValue>(TValue value, dynamic element, string paramName, ExceptionCustomizations? exceptionCustomizations)
where TValue : notnull, IEnumerable
{
bool notAll = false;
foreach (var item in value)
{
if (item != element)
{
notAll = true;
if (notAll) break;
}
}
if (!notAll) ExceptionThrower.Throw(paramName, exceptionCustomizations, $"Collection should contain at least one occurences of an element not of the same value as the element {element}.");
}

}