Swallow.Validation
0.6.1
See the version list below for details.
dotnet add package Swallow.Validation --version 0.6.1
NuGet\Install-Package Swallow.Validation -Version 0.6.1
<PackageReference Include="Swallow.Validation" Version="0.6.1" />
paket add Swallow.Validation --version 0.6.1
#r "nuget: Swallow.Validation, 0.6.1"
// Install Swallow.Validation as a Cake Addin
#addin nuget:?package=Swallow.Validation&version=0.6.1
// Install Swallow.Validation as a Cake Tool
#tool nuget:?package=Swallow.Validation&version=0.6.1
Swallow.Validation
A lightweight, fluent-style validation library for C#. But what does that mean? That means minimal dependencies (none, actually) and great programmer experience. If you've seen Fluent Assertions, you might find some similarities.
Getting started
Validating values
A validation is created using Validator.Check()
. To then actually validate a value, call
That()
on the validator followed by Satisfies()
:
Validator.Check()
.That(() => myValue).Satisfies(x => x > 1, "be larger than 1")
You can chain another validation rule directly after the Satisfies
the same as before:
Validator.Check()
.That(() => myValue).Satisfies(x => x > 1, "be larger than 1")
.That(() => myName).Satisfies(s => s != null, "not be null")
See that nice string? It determines what the validation error will say if the predicate is
not met - if myName
is null
, a validation error saying "myName must not be null"
will
be produced. The name of the value is automatically determined, but you can of course pass it
yourself, too!
Validator.Check()
.That(() => myValue, "ThatValue").Satisfies(x => x > 1, "be larger than 1")
.That(() => myName, "ThatName").Satisfies(s => s != null, "not be null")
To actually retrieve the validation errors - or a positive result - you can use Then()
.
var result = Validator.Check()
.That(() => myValue, "ThatValue").Satisfies(x => x > 1, "be larger than 1")
.That(() => myName, "ThatName").Satisfies(s => s != null, "not be null")
.Then(() => new MyFancyClass(myValue, myName));
The function is executed only when there are no validation errors. What you get is a
ValidationResult<MyFancyClass>
where you can check the status with IsSuccess
,
get a list of all errors with Errors
or the created value with Value
.
If you don't need a result and only want to handle errors, you can similarily use Else()
:
Validator.Check()
.That(() => myValue, "ThatValue").Satisfies(x => x > 1, "be larger than 1")
.That(() => myName, "ThatName").Satisfies(s => s != null, "not be null")
.Else(errs => throw new Exception($"{errs.Count} validation errors happened!"));
Conditional validation
If you have a validation rule that should only be checked on certain conditions, you can add
a When()
-call after the Satisfies()
to specify when to validate and when to skip.
Validator.Check()
.That(() => myName).Satisfies(s => s != null, "not be null")
.That(() => myName).Satisfies(s => s.Length > 1, "not be empty").When(() => myName != null)
This way, s.Length > 1
is only executed iff myName
is not null
- no NullReferenceException
here.
Custom validation errors
Passing a string to Satisfies()
is a simple way to control the resulting validation error,
but why stop there?
class IsNullError : ValidationError
{
public override string ToString() => $"{PropertyName} is null when it's not supposed to!";
}
...
Validator.Check()
.That(() => myName).Satisfies(s => s != null, _ => new IsNullError())
Named assertions
Using Satisfies()
over and over again and specifying the very same predicate and error all
over the place is not very DRY, so you can instead provide extension methods to give these
assertions memorable names:
public static class MyAssertions
{
public static IConditionable<IsNullError> IsNotNull<T>(this IAssertable<T> property)
{
return property.Satisfies(x => x != null, _ => new IsNullError());
}
}
...
Validator.Check()
.That(() => myName).IsNotNull()
Single-call assertions
If you do not like having to call two or three methods for a single validation, you can instead
put everything into a combined That()
-call:
Validator.Check()
.That(() => myName, a => a.IsNotNull(a))
.That(() => myValue, x => x > 1, () => myName != null)
This will simply expand to:
Validator.Check()
.That(() => myName).IsNotNull()
.That(() => myValue).Satisfies(x => x > 1, "satisfy predicate").When() => myName != null)
Use classes as assertions
If your assertion is too complex for a simple lambda, you might want to use a custom asserter.
An asserter inherits from IAsserter<TValue, TError>
and implements the Check()
method.
public sealed class MyAsserter : IAsserter<string, GenericValidationError>
{
public bool Check(string value, out GenericValidationError error)
{
if (someComplexClass.CallComplexMethod(value) == INVALID_VALUE)
{
error = new GenericValidationError("be a valid foo");
return false;
}
error = null;
return true;
}
}
...
Validator.Check()
.That(() => someValue).Satisfies(new MyAsserter())
Going deeper
If you wish to know more about the validations and what you can do with them, I suggest you just find out by digging through the code or just using the library to build some validations.
And if you feel like something is missing (or just plain broken), feel free to create an issue.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Swallow.Validation:
Package | Downloads |
---|---|
Swallow.Validation.ServiceCollection
A lightweight, fluent-style validation library |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
7.0.0 | 1,675 | 1/20/2024 |
6.0.1 | 1,064 | 7/2/2023 |
6.0.0 | 2,094 | 1/22/2023 |
5.0.1 | 714 | 11/13/2022 |
4.2.0 | 833 | 6/20/2022 |
4.1.1 | 585 | 5/29/2022 |
4.1.0 | 761 | 2/13/2022 |
4.0.0 | 514 | 2/13/2022 |
3.1.0 | 22,325 | 6/5/2021 |
3.0.0 | 451 | 5/20/2021 |
2.0.0 | 441 | 3/6/2021 |
1.5.0 | 2,217 | 11/23/2020 |
1.4.0 | 415 | 9/4/2020 |
1.3.0 | 580 | 7/20/2020 |
1.2.0 | 1,359 | 6/4/2020 |
1.1.1 | 459 | 5/9/2020 |
1.1.0 | 439 | 5/5/2020 |
1.0.0 | 553 | 4/29/2020 |
0.12.3 | 483 | 4/5/2020 |
0.12.2 | 442 | 4/3/2020 |
0.12.1 | 11,246 | 3/16/2020 |
0.12.0 | 479 | 3/14/2020 |
0.11.2 | 572 | 2/29/2020 |
0.11.1 | 525 | 2/16/2020 |
0.11.0 | 511 | 2/13/2020 |
0.10.3 | 499 | 2/12/2020 |
0.10.2 | 544 | 1/31/2020 |
0.10.1 | 510 | 1/27/2020 |
0.10.0 | 507 | 1/5/2020 |
0.9.1 | 463 | 1/3/2020 |
0.8.0 | 451 | 12/21/2019 |
0.7.3 | 4,918 | 11/27/2019 |
0.7.2 | 466 | 11/9/2019 |
0.7.1 | 451 | 11/9/2019 |
0.7.0 | 469 | 11/9/2019 |
0.6.1 | 461 | 10/27/2019 |
0.5.3 | 465 | 10/23/2019 |
0.5.2 | 448 | 10/21/2019 |
0.5.1 | 452 | 10/20/2019 |
0.4.2 | 488 | 9/14/2019 |
0.4.1 | 484 | 9/7/2019 |
0.3.3 | 482 | 9/7/2019 |
0.3.2 | 531 | 8/28/2019 |
0.3.1 | 501 | 8/24/2019 |
0.2.4 | 481 | 8/24/2019 |
0.2.3 | 554 | 8/24/2019 |