-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExpressValidator.TOptions.cs
More file actions
101 lines (92 loc) · 2.95 KB
/
ExpressValidator.TOptions.cs
File metadata and controls
101 lines (92 loc) · 2.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
using FluentValidation.Results;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace ExpressValidator
{
/// <summary>
/// Defines a validator for an object with options.
/// </summary>
/// <typeparam name="TObj"></typeparam>
/// <typeparam name="TOptions"></typeparam>
public class ExpressValidator<TObj, TOptions> : IExpressValidator<TObj>
{
private readonly IEnumerable<IObjectValidator<TObj, TOptions>> _validators;
private readonly OnFirstPropertyValidatorFailed _validationMode;
internal ExpressValidator(TOptions options, IEnumerable<IObjectValidator<TObj, TOptions>> validators, OnFirstPropertyValidatorFailed validationMode)
{
_validators = validators;
_validationMode = validationMode;
foreach (var validator in _validators)
{
validator.ApplyOptions(options);
}
}
public ValidationResult Validate(TObj obj)
{
if (_validators.Any(v => v.IsAsync))
{
throw new InvalidOperationException($"Object validator has a property or field with asynchronous validation rules. Please use {nameof(ValidateAsync)} method.");
}
return _validationMode == OnFirstPropertyValidatorFailed.Break ? ValidateWithBreak(obj) : ValidateWithContinue(obj);
}
public Task<ValidationResult> ValidateAsync(TObj obj, CancellationToken token = default)
{
return _validationMode == OnFirstPropertyValidatorFailed.Break ? ValidateWithBreakAsync(obj, token) : ValidateWithContinueAsync(obj, token);
}
private async Task<ValidationResult> ValidateWithBreakAsync(TObj obj, CancellationToken token)
{
foreach (var validator in _validators)
{
token.ThrowIfCancellationRequested();
var (IsValid, Failures) = await validator.ValidateAsync(obj, token).ConfigureAwait(false);
if (!IsValid)
{
return new ValidationResult(Failures);
}
}
return new ValidationResult();
}
private async Task<ValidationResult> ValidateWithContinueAsync(TObj obj, CancellationToken token)
{
var currentFailures = new List<ValidationFailure>();
foreach (var validator in _validators)
{
token.ThrowIfCancellationRequested();
var (IsValid, Failures) = await validator.ValidateAsync(obj, token);
if (!IsValid)
{
currentFailures.AddRange(Failures);
}
}
return new ValidationResult(currentFailures);
}
private ValidationResult ValidateWithBreak(TObj obj)
{
foreach (var validator in _validators)
{
var (IsValid, Failures) = validator.Validate(obj);
if (!IsValid)
{
return new ValidationResult(Failures);
}
}
return new ValidationResult();
}
private ValidationResult ValidateWithContinue(TObj obj)
{
var currentFailures = new List<ValidationFailure>();
foreach (var validator in _validators)
{
var (IsValid, Failures) = validator.Validate(obj);
if (!IsValid)
{
currentFailures.AddRange(Failures);
}
}
return new ValidationResult(currentFailures);
}
}
}