-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Hide validator behind validator interface
- Loading branch information
1 parent
1dcc286
commit e38d7a1
Showing
4 changed files
with
193 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using Lemonad.ErrorHandling.Internal; | ||
|
||
namespace Lemonad.ErrorHandling { | ||
/// <summary> | ||
/// An <typeparamref name="TError"/> collection of <typeparamref name="TError"/> based on validations of <typeparamref name="T"/>. | ||
/// </summary> | ||
/// <typeparam name="T"> | ||
/// The type of the validation candidate. | ||
/// </typeparam> | ||
/// <typeparam name="TError"> | ||
/// The type of the the error type. | ||
/// </typeparam> | ||
public interface IValidator<out T, TError> : IReadOnlyCollection<TError> { | ||
/// <summary> | ||
/// Validate <typeparamref name="T"/> with an <paramref name="predicate"/> function and set the failure type in <paramref name="errorSelector"/>. | ||
/// </summary> | ||
/// <param name="predicate"> | ||
/// A function to test <typeparamref name="T"/> for a condition. | ||
/// </param> | ||
/// <param name="errorSelector"> | ||
/// A function to set the error if the predicate function would return false. | ||
/// </param> | ||
/// <returns> | ||
/// An <see cref="Validator{T,TError}"/>. | ||
/// </returns> | ||
IValidator<T, TError> Validate(Func<T, bool> predicate, Func<T, TError> errorSelector); | ||
|
||
/// <summary> | ||
/// Validate <typeparamref name="T"/> with an <paramref name="predicate"/> function and set the failure type with <paramref name="error"/>. | ||
/// </summary> | ||
/// <param name="predicate"> | ||
/// A function to test <typeparamref name="T"/> for a condition. | ||
/// </param> | ||
/// <param name="error"> | ||
/// The error value. | ||
/// </param> | ||
/// <returns> | ||
/// An <see cref="Validator{T,TError}"/>. | ||
/// </returns> | ||
IValidator<T, TError> Validate(Func<T, bool> predicate, TError error); | ||
|
||
/// <summary> | ||
/// Gets the <see cref="IResult{T,TError}"/>. | ||
/// </summary> | ||
IResult<T, IReadOnlyCollection<TError>> Result { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using Lemonad.ErrorHandling.Extensions; | ||
|
||
namespace Lemonad.ErrorHandling.Internal { | ||
internal readonly struct Validator<T, TError> : IValidator<T, TError> { | ||
private readonly T _candidate; | ||
private readonly Queue<TError> _errors; | ||
|
||
public IResult<T, IReadOnlyCollection<TError>> Result { get; } | ||
|
||
internal Validator(T candidate) { | ||
_candidate = candidate; | ||
_errors = new Queue<TError>(); | ||
Result = ErrorHandling.Result.Value<T, IReadOnlyCollection<TError>>(_candidate); | ||
} | ||
|
||
private Validator(in Queue<TError> errors, in T candidate) { | ||
_errors = new Queue<TError>(errors); | ||
_candidate = candidate; | ||
Result = _errors.Count > 0 | ||
? ErrorHandling.Result.Error<T, IReadOnlyCollection<TError>>(_errors) | ||
: ErrorHandling.Result.Value<T, IReadOnlyCollection<TError>>(_candidate); | ||
} | ||
|
||
public IEnumerator<TError> GetEnumerator() => _errors.GetEnumerator(); | ||
|
||
public IValidator<T, TError> Validate(Func<T, bool> predicate, Func<T, TError> errorSelector) { | ||
if (predicate == null) throw new ArgumentException(nameof(predicate)); | ||
if (errorSelector == null) throw new ArgumentException(nameof(errorSelector)); | ||
var result = _candidate.ToResult(predicate, errorSelector); | ||
// This refers to the initial queue. | ||
if (result.Either.HasError) _errors.Enqueue(result.Either.Error); | ||
return new Validator<T, TError>(_errors, _candidate); | ||
} | ||
|
||
public IValidator<T, TError> Validate(Func<T, bool> predicate, TError error) => Validate(predicate, _ => error); | ||
|
||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | ||
|
||
public int Count => _errors.Count; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,20 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System; | ||
using Lemonad.ErrorHandling.Internal; | ||
|
||
namespace Lemonad.ErrorHandling { | ||
/// <summary> | ||
/// An <typeparamref name="TError"/> collection of <typeparamref name="TError"/> based on validations of <typeparamref name="T"/>. | ||
/// </summary> | ||
/// <typeparam name="T"> | ||
/// The type of the validation candidate. | ||
/// </typeparam> | ||
/// <typeparam name="TError"> | ||
/// The type of the the error type. | ||
/// </typeparam> | ||
public readonly struct Validator<T, TError> : IReadOnlyCollection<TError> { | ||
private readonly T _candidate; | ||
private readonly Queue<TError> _errors; | ||
|
||
/// <summary> | ||
/// Convert to a <see cref="Result{T,TError}"/>. | ||
/// </summary> | ||
public IResult<T, IReadOnlyCollection<TError>> Result { | ||
get { | ||
var candidate = _candidate; | ||
return _errors.ToResultError<T, IReadOnlyCollection<TError>>(x => x.Count > 0, _ => candidate); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Creates an instance of <see cref="Validator{T,TError}"/>. | ||
/// </summary> | ||
/// <param name="candidate"> | ||
/// The validation <paramref name="candidate"/>. | ||
/// </param> | ||
public Validator(T candidate) { | ||
_candidate = candidate; | ||
_errors = new Queue<TError>(); | ||
} | ||
|
||
private Validator(in Queue<TError> errors, in T candidate) { | ||
_errors = errors; | ||
_candidate = candidate; | ||
} | ||
|
||
/// <inheritdoc cref="IEnumerable{T}.GetEnumerator"/> | ||
public IEnumerator<TError> GetEnumerator() => _errors.GetEnumerator(); | ||
|
||
/// <summary> | ||
/// Validate <typeparamref name="T"/> with an <paramref name="predicate"/> function and set the failure type in <paramref name="errorSelector"/>. | ||
/// </summary> | ||
/// <param name="predicate"> | ||
/// A function to test <typeparamref name="T"/> for a condition. | ||
/// </param> | ||
/// <param name="errorSelector"> | ||
/// A function to set the error if the predicate function would return false. | ||
/// </param> | ||
/// <returns> | ||
/// An <see cref="Validator{T,TError}"/>. | ||
/// </returns> | ||
public Validator<T, TError> Validate(Func<T, bool> predicate, Func<TError> errorSelector) { | ||
var result = _candidate.ToResult(predicate, _ => errorSelector()); | ||
if (result.Either.HasError) _errors.Enqueue(result.Either.Error); | ||
return new Validator<T, TError>(_errors, _candidate); | ||
} | ||
|
||
/// <summary> | ||
/// Validate <typeparamref name="T"/> with an <paramref name="predicate"/> function and set the failure type with <paramref name="error"/>. | ||
/// </summary> | ||
/// <param name="predicate"> | ||
/// A function to test <typeparamref name="T"/> for a condition. | ||
/// </param> | ||
/// <param name="error"> | ||
/// The error value. | ||
/// </param> | ||
/// <returns> | ||
/// An <see cref="Validator{T,TError}"/>. | ||
/// </returns> | ||
public Validator<T, TError> Validate(Func<T, bool> predicate, TError error) => Validate(predicate, () => error); | ||
|
||
/// <inheritdoc cref="IEnumerable.GetEnumerator"/> | ||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | ||
|
||
/// <inheritdoc cref="IReadOnlyCollection{T}.Count"/> | ||
public int Count => _errors.Count; | ||
public static class Validator { | ||
public static IValidator<T, TError> Value<T, TError>(T value) => new Validator<T, TError>(value); | ||
|
||
public static IValidator<T, TError> Value<T, TError>( | ||
T value, | ||
Func<T, bool> predicate, | ||
Func<T, TError> errorSelector | ||
) => new Validator<T, TError>(value).Validate(predicate, errorSelector); | ||
|
||
public static IValidator<T, TError> Value<T, TError>( | ||
T value, | ||
Func<T, bool> predicate, | ||
TError errorSelector | ||
) => new Validator<T, TError>(value).Validate(predicate, errorSelector); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters