Open alexinea opened 3 years ago
Leo's own Validation will not include "business specific" validators, nor will it include complex validators. (In the design of Leo Validation, we call the validator "ValueToken").
We will provide a way for users to integrate third-party verification solutions in Leo Validation. For example, integrate FluentValidation or the DataAnnotation that comes with .NET into Leo Validation. But we will not directly integrate, nor will we provide integrated extension packages. But we will tell you how to integrate, and the method will be included in the "samples" folder.
The author of NMS.Leo.Typed, @alexinea, will provide a complete scheme of validation design in cosmos-loops/Cosmos.Validation.
By then, users can either integrate cosmos-loops/Cosmos.Validation into Leo Validation as a third-party solution, or integrate Leo Validation into cosmos-loops/Cosmos.Validation.
Token Name | Status | Generic Version | Alias | With Message | Features |
---|---|---|---|---|---|
Null | Avaliable ✔ | ⚪ | ⚪ | ✔ | ⚪ |
NotNull | Avaliable ✔ | ⚪ | ⚪ | ✔ | ⚪ |
Empty | Avaliable ✔ | ⚪ | ⚪ | ✔ | ⚪ |
NotEmpty | Avaliable ✔ | ⚪ | Required | ✔ | ⚪ |
Equal | Avaliable ✔ | ✔ | ⚪ | ✔ | ⚪ |
NotEqual | Avaliable ✔ | ✔ | ⚪ | ✔ | ⚪ |
LessThan | Avaliable ✔ | ✔ | ⚪ | ✔ | ⚪ |
LessThanOrEqual | Avaliable ✔ | ✔ | ⚪ | ✔ | ⚪ |
GreaterThan | Avaliable ✔ | ✔ | ⚪ | ✔ | ⚪ |
GreaterThanOrEqual | Avaliable ✔ | ✔ | ⚪ | ✔ | ⚪ |
Length | Avaliable ✔ | ⚪ | ⚪ | ✔ | ⚪ |
MaxLength | Avaliable ✔ | ⚪ | ⚪ | ✔ | ⚪ |
MinLength | Avaliable ✔ | ⚪ | AtLeast | ✔ | ⚪ |
Range | Avaliable ✔ | ✔ | ⚪ | ✔ | ⚪ |
RangeWithOpenInterval | Avaliable ✔ | ✔ | ⚪ | ✔ | ✔ |
RangeWithCloseInterval | Avaliable ✔ | ✔ | ⚪ | ✔ | ✔ |
Func | Avaliable ✔ | ✔ | Must | ✔ | ⚪ |
Predicate | Avaliable ✔ | ✔ | ⚪ | ✔ | ⚪ |
RegularExpression | Avaliable ✔ | ⚪ | ⚪ | ✔ | ⚪ |
Enum | Avaliable ✔ | ✔ | ⚪ | ✔ | ⚪ |
StringEnum | Avaliable ✔ | ✔ | ⚪ | ✔ | ⚪ |
Type | Avaliable ✔ | ✔ | ⚪ | ✔ | ✔ |
Types | Avaliable ✔ | ✔ | ⚪ | ✔ | ✔ |
ScalePrecision | Avaliable ✔ | ⚪ | ⚪ | ✔ | ⚪ |
In | Avaliable ✔ | ✔ | ⚪ | ✔ | ✔ |
NotIn | Avaliable ✔ | ✔ | ⚪ | ✔ | ✔ |
Any | Avaliable ✔ | ✔ | NotAll | ✔ | ✔ |
All | Avaliable ✔ | ✔ | NotAny | ✔ | ✔ |
Items for Null and NotNull | WIP 🚧 | ✔ ❕ | ⚪ | ⚪ | ✔ |
Items for Empty and NotEmpty | Intend ✒ | ✔ ❕ | ⚪ | ⚪ | ✔ |
Items for Equal and NotEqual | Intend ✒ | ✔ ❕ | ⚪ | ⚪ | ✔ |
Items for LT, LToE, GT and GToE | Intend ✒ | ✔ ❕ | ⚪ | ⚪ | ✔ |
Items for Length , MaxLen and MinLen | Intend ✒ | ✔ ❕ | ⚪ | ⚪ | ✔ |
Items for Range, RangeO and RangeC | Intend ✒ | ✔ ❕ | ⚪ | ⚪ | ✔ |
Items for Type and Types | Intend ✒ | ✔ ❕ | ⚪ | ⚪ | ✔ |
Items for In and NotIn | Intend ✒ | ✔ ❕ | ⚪ | ⚪ | ✔ |
Items for All and Any | Intend ✒ | ✔ ❕ | ⚪ | ⚪ | ✔ |
Range
Token will contain one parameter: RangeOptions, the value is:
Mutually Exclusive
indicates that the Token of the same type is mutually exclusive;Mutually Exclusive Flags
means that different types of Token are mutually exclusive.Flag Value | Value Tokens |
---|---|
90111 | Null , MaxAndMinLength |
90112 | Null , MaxLength |
90113 | Null , MinLength |
90114 | Null , NotNull |
90115 | Empty , MaxAndMinLength |
90116 | Empty , MaxLength |
90117 | Empty , MinLength |
90118 | NotEmpty , Empty |
90119 | MaxLength , MaxAndMinLength |
90120 | MinLength , MaxAndMinLength |
Equal/Equal<TVal>
tokenNotEqual/NotEqual<TVal>
tokenRange/Range<TVal>
token (includes RangeWithOpenInterval
and RangeWithCloseInterval
)Func/Func<TVal>
token (includes Must
)Predicate/Predicate<TVal>
tokenIn/In<TVal>
tokenNotIn/NotIn<TVal>
tokenAny/Any<TVal, TItem>
token (includes NotAll
and NotAll<TVal>
)All/All<TVal, TItem>
token (includes NotAny
and NotAny<TVal>
)LessThan/LessThan<TVal>
tokenLessThanOrEqual/LessThanOrEqual<TVal>
tokenGreaterThan/GreaterThan<TVal>
tokenGreaterThanOrEqual/GreaterThanOrEqual<TVal>
tokenEnum
tokenStringEnum
tokenAdd two other tokens that are equal to ValueToken:
When
, Or
and And
)Items
)IterationToken can be used if and only if TVal is an iterable type under a generic interface.
In some application solutions, we need to check and verify data, and filter out illegal or unreasonable data. Therefore, it is necessary to integrate a validator in LeoVisitor so that it can be verified directly during the setup phase.
Since the requirement of the validator is not a general requirement, adding validation to the core library
DictBase
will pay extra. Therefore, it is an ideal choice to add an optional verification context in LeoVisitor to implement data verification.I will record this part of the notes here in the form of a memo.
Set verification policy at creation time
To set the validation rules when creating LeoVisitor, we can pass in a strategy object (which implements the
ILeoValidationStrategy
interface) to theLeoVisitorFactory
factory method:For LeoVisitor created with an initial data set (IDictionary implementation), the verification strategy can also be passed in when creating:
Set or override the verification strategy in LeoVisitor
An API should be provided so that verification rules can be set or updated on LeoVisitor:
When to verify data
When LeoVisitor is created and a strategy is given, the value in LeoVisitor should not be checked immediately. I think it should be checked when the results are obtained to avoid time-consuming creation.
We may need to provide a parameter to indicate whether the policy is strict or non-strict. When using strict rules, each of our SetValue operations will check the value; when using non-strict rules, we will perform a check only when we get the verification result.
This applies to both instance setters and value setters.
Support for other verification components
Do we need to consider supporting other verification components? For example, tell users how to extend LeoVisitor's verification capabilities to integrate FluentValidation?
In addition, do we need to support the DataAnnotation that comes with .NET?
How to extend the support for user-designed verification components? This requires us to discuss together.
Throw an exception, or silently collect errors?
For LeoVisitor, I think the silent mode is more suitable. Throwing an exception directly loses the original intention of verifying data. We should be able to obtain a set of error messages so that we can return and inform the user.
Of course, for similar low-code platforms, they should be able to verify data at the front end. Then the LeoVisitor verifier at the back end can be regarded as a two-stage verification. So throwing exceptions directly is not in practice. Of course, we can provide a pair of APIs, similar to
Verify
andVerifyAndThrow
.At last
I think LeoVisitor's validator should not be designed to be too complicated and too many functions. Even, whether we should use Fluent APIs is a matter of thinking. Fluent APIs can make the code difficult to read in this case.