IOKode.OpinionatedFramework.Generators.Ensuring
1.0.1-preview3
Prefix Reserved
See the version list below for details.
dotnet add package IOKode.OpinionatedFramework.Generators.Ensuring --version 1.0.1-preview3
NuGet\Install-Package IOKode.OpinionatedFramework.Generators.Ensuring -Version 1.0.1-preview3
<PackageReference Include="IOKode.OpinionatedFramework.Generators.Ensuring" Version="1.0.1-preview3" />
paket add IOKode.OpinionatedFramework.Generators.Ensuring --version 1.0.1-preview3
#r "nuget: IOKode.OpinionatedFramework.Generators.Ensuring, 1.0.1-preview3"
// Install IOKode.OpinionatedFramework.Generators.Ensuring as a Cake Addin #addin nuget:?package=IOKode.OpinionatedFramework.Generators.Ensuring&version=1.0.1-preview3&prerelease // Install IOKode.OpinionatedFramework.Generators.Ensuring as a Cake Tool #tool nuget:?package=IOKode.OpinionatedFramework.Generators.Ensuring&version=1.0.1-preview3&prerelease
Overview
OpinionatedFramework Ensure API is a comprehensive library written in C# for the validation of preconditions, postconditions, and invariants.
One of the main features of this library is the ability to customize the exception thrown during each validation. It also excels in its extensibility, making it easy to add new validations.
While the Ensure API is part of the OpinionatedFramework, it is distributed in a separately NuGet package and remains decoupled from it.
Installing
Install the NuGet package IOKode.OpinionatedFramework.Ensuring
.
Getting started
The static Ensure
class serves as the entry point to the library's functionality. The API is designed to offer natural usage to the developers.
The basic usage of the API follows this pattern:
Ensure.{Validation Category}.{Validation}.ElseThrows(exception);
Let's take a look at some examples:
Ensure.Stream.CanRead(dataStream).ElseThrows(new InvalidOperationException("Cannot read the stream."));
Ensure.String.IsNotNullOrEmpty(firstName).ElseThrows(new ArgumentNullException(nameof(firstName)));
Built-in validations category (ensurers)
Each "validation category" is called "ensurer".
There are seven built-in ensurers available. Take a look in the source code:
Boolean
Enumerable
Number
Object
Stream
String
Type
Adding custom ensurers
Extending the Ensure API with custom validations is straightforward. First, you need to reference the IOKode.OpinionatedFramework.Generators.Ensuring
package:
<ItemGroup>
<PackageReference Include="IOKode.OpinionatedFramework.Ensuring" Version="1.0.1" />
<PackageReference Include="IOKode.OpinionatedFramework.Generators.Ensuring" Version="1.0.1" PrivateAssets="all" />
</ItemGroup>
Next, you should create a static class with public static methods that return a boolean value and decorate the class with the [Ensurer]
attribute. The class name should end with Ensurer
. A set of source-generators take care of generating the Ensure
class and other needed stuff.
Here's an example of a custom ensurer for the Person
class.
[Ensurer]
public static class PersonEnsurer
{
public static bool IsInLegalAge(Person person)
{
return person.Age >= 18;
}
}
That's all. Now you can use it:
Ensure.Person.IsInLegalAge(john).ElseThrows(new PersonIsUnderLegalAgeException(john));
Custom exception throwing
ElseThrows
method will throw the exception if the validation not passes.
To make exception selection more convenient, the library includes a set of extension methods:
ElseThrowsNullArgument(string paramName)
// throws ArgumentNullExceptionElseThrowsIllegalArgument(string paramName, string message)
// throws ArgumentExceptionElseThrowsInvalidOperation(string message)
// throws InvalidOperationExceptionElseThrowsBase(string message)
// throws Exception
Using these extension methods, the previous examples can be rewritten as:
Ensure.Stream.CanRead(dataStream).ElseThrowsInvalidOperation("Cannot read the stream.");
Ensure.String.IsNotNullOrEmpty(firstName).ElseThrowsNullArgument(nameof(firstName));
These methods provide a convenient way to throw custom exceptions that best fit the context of your application.
Adding your own extension methods for throwing
You're free to add your own extension methods for throwing exceptions as needed.
The responsible of throwing the exception is the Thrower
class, so you can add an extension method like this:
public static class PersonThrowerExtensions
{
public static void ElseThrowsPersonUnderLegalAge(this Thrower thrower, Person person)
{
var exception = new PersonIsUnderLegalAgeException(person);
thrower.ElseThrows(exception);
}
}
To use this extension method, simply call it like you would call the pre-existing exception extension methods:
Ensure.Person.IsInLegalAge(john).ElseThrowsPersonUnderLegalAge(john);
In the above line, we used a custom ensurer and an a custom thrower's extension method.
Behind the scenes
When utilizing the OpinionatedFramework Ensure API, you are harnessing a chain of calls that seamlessly connect your validation logic with exception handling. Let's unpack this chain to understand how it functions.
Ensurer
: The staticEnsurer
class is the entry point of the validation API. It's is a generated class that contains properties that correspond to eachEnsurerThrowers
– bridges between Ensurers and the Thrower.
// Generated code
public static class Ensurer
{
// Other Ensurer-Thrower bridges
public static PersonEnsurerThrower Person => new PersonEnsurerThrower();
// Other Ensurer-Thrower bridges
}
{EnsurerName}EnsurerThrower
: For each ensurer, a corresponding{EnsurerName}EnsurerThrower
class is generated. This class comprises all methods from the original ensurer, but instead of returning a boolean, it yields an instance of theThrower
class.
// Generated code
public class PersonEnsurerThrower
{
public Thrower IsInLegalAge(Person person)
{
bool isValid = PersonEnsurer.IsInLegalAge(person); // Call to the Ensurer's static method.
return new Thrower(isValid); // Returns a Thrower instance with the validation result.
}
}
Thrower
: TheThrower
instance returned by the{EnsurerName}EnsurerThrower
carries the result of the validation check. By calling theElseThrows(Exception)
method on theThrower
instance, an exception is thrown if the validation has not passed.
Ensurer // Entry point
.Person // Returns the Ensurer-Thrower bridge
.IsInLegalAge(john) // Returns a Thrower instance
.ElseThrows(new PersonIsUnderLegalAgeException(john)) // Throws the exception if the validation has not passed
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- Microsoft.CodeAnalysis.CSharp (>= 4.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.1.0 | 219 | 6/21/2023 |
1.0.4 | 156 | 6/18/2023 |
1.0.3 | 159 | 6/18/2023 |
1.0.2 | 153 | 6/18/2023 |
1.0.1 | 185 | 6/3/2023 |
1.0.1-preview3 | 225 | 6/3/2023 |
1.0.1-preview1 | 283 | 6/3/2023 |
0.3.0-dev | 98 | 5/28/2024 |
0.2.0-dev | 91 | 5/28/2024 |