Syrx.Validation 2.0.0

dotnet add package Syrx.Validation --version 2.0.0
NuGet\Install-Package Syrx.Validation -Version 2.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Syrx.Validation" Version="2.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Syrx.Validation --version 2.0.0
#r "nuget: Syrx.Validation, 2.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Syrx.Validation as a Cake Addin
#addin nuget:?package=Syrx.Validation&version=2.0.0

// Install Syrx.Validation as a Cake Tool
#tool nuget:?package=Syrx.Validation&version=2.0.0

Syrx.Validation

A tiny little library with a very simple precondition checker and a handful of validation attributes.

What

The precondition checker the Contract class is probably the most useful as it can be used by any method. The Validator is pretty useful too, but really only useful for POCOs that are decorated with validation attributes.

Why

Checking conditions in your code is a good thing but it can get really verbose really quickly and ruin the readbility/intent of your code. More often than not, precondition checks take the form of multiline if (condition) throw exception statements. We wrote this library to convert the multiline statements into single line statements and give you control over which exceptions are thrown when the condition fails.

Example

In one of the finest traditions of our craft, let's take a look at a contrived and trivial example.

Let's assume we have a basic Person class which we'll be saving to a database. Seems pretty straightforward, right? Here's what the Person looks like without any validation.

No validation

public class Person
{
    public string Name { get; }
    public DateTime DateOfBirth { get; }

    public Person(string name, DateTime dateOfBirth)
    {
        Name = name;
        DateOfBirth = dateOfBirth;
    }
}

What could go wrong?

Hold my beer...

We said earlier we'd be saving the Person to a database. Here - in no particular order - are a couple of things that could go wrong.

  • No name supplied. Oops.
  • Name is supplied to the class. It's 51 characters long but the field on the table can only hold 50. Oops.
  • DateOfBirth is equal to either DateTime.MinValue, DateTime.MaxValue or is sometime in the future. Oops.

Vanilla Validation

Okay, so we want to catch those pesky validation problems while we instantiate our Person. Using the traditional if (condition) throw exception approach, our class might now look like this which - in my humble opinion - ain't too cool.

While it does the job of catching validation problems, it's caused our simple class to look quite a bit less simple. The premise behind the if statements is if (false) throw exception.

public class Person
{
    public string Name { get; }
    public DateTime DateOfBirth { get; }

    public Person(string name, DateTime dateOfBirth)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            throw new ArgumentNullException(nameof(name));
        }

        if (name.Length >= 50)
        {
            throw new ArgumentOutOfRangeException(nameof(name));
        }

        if (dateOfBirth == DateTime.MinValue || 
            dateOfBirth == DateTime.MaxValue || 
            dateOfBirth > DateTime.Now)
        {
            throw new ArgumentOutOfRangeException(nameof(dateOfBirth));
        }

        Name = name;
        DateOfBirth = dateOfBirth;
    }
}

Better, I think.

Using the Contract precondtion checker we can collapse those conditions into much simpler statements - require the condition to be true, otherwise throw an exception.

using static Syrx.Validation.Contract;

public class Person
{
    public string Name { get; }
    public DateTime DateOfBirth { get; }

    public Person(string name, DateTime dateOfBirth)
    {
        Throw<ArgumentNullException>(!string.IsNullOrWhiteSpace(name), nameof(name));
        Throw<ArgumentOutOfRangeException>(name.Length <= 50, nameof(name));
        Throw<ArgumentOutOfRangeException>(!(dateOfBirth == DateTime.MinValue ||
                                               dateOfBirth == DateTime.MaxValue ||
                                               dateOfBirth > DateTime.Now), nameof(dateOfBirth));

        Name = name;
        DateOfBirth = dateOfBirth;
    }
}

Now with added delegates!

Useful as the Throw<T> method is, it can be a little limiting when you need very fine control over the exception. Never fear though - the latest version now allows you to pass your own Func<TException> delegate to be invoked if your required condition evaluates to false.

Using our super trivial example again, our validation can be re-written again. It's functionally equivalent, and a couple more keystrokes, but shows how you can roll your own exception invocation.

using static Syrx.Validation.Contract;

public class Person
{
    public string Name { get; }
    public DateTime DateOfBirth { get; }

    public Person(string name, DateTime dateOfBirth)
    {
        Throw(!string.IsNullOrWhiteSpace(name), () => new ArgumentNullException(nameof(name)));
        Throw(name.Length <= 50, () => new ArgumentOutOfRangeException(nameof(name)));
        Throw(!(dateOfBirth == DateTime.MinValue || 
                  dateOfBirth == DateTime.MaxValue ||
                  dateOfBirth > DateTime.Now), () => new ArgumentOutOfRangeException(nameof(dateOfBirth)));
        
        Name = name;
        DateOfBirth = dateOfBirth;
    }
}

That's great! Where can I get this?

Nuget, of course.

Install-Package Syrx.Validation

Anything else I should know?

First, I find that the Contract.Throw<T> method is insanely useful. Your mileage may vary. You might like using this library. Then again, you might not. I hope you do.

Second, this is probably the most documentation that you're going to get on this. It's a really simple library and you're smart.

Thanks!

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net6.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on Syrx.Validation:

Package Downloads
Syrx.Settings.Databases

A collection of classes used for managing the configuration of Syrx implementations against relational databases.

Syrx.Connectors.Databases

Creates connections to relational databases.

Syrx.Readers.Databases

Reads commands for relational databases from configration sources.

Syrx.AspNetCore.Configuration

A package that can be used to register Syrx components seamlessly in ASP.NET Core applications.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.0.0 61 6/10/2024
1.2.0 580 9/27/2019
1.1.0 789 8/25/2018
1.0.0 12,717 10/1/2017

Now with added delegates!