Zentient Results Api Reference Overview - ulfbou/Zentient.Results GitHub Wiki
Zentient.Results is a powerful .NET 9.0 library designed to improve how you handle operation outcomes and errors. It moves away from traditional exception-based control flow, introducing a Result type that clearly communicates whether an operation succeeded with a value or failed with structured error information.
This library helps you write more predictable and maintainable code. Instead of relying on exceptions for routine error conditions, Zentient.Results empowers you to:
-
Model Outcomes Clearly: A method returning
IResult<T>
explicitly signals that it might produce aT
or a failure. - Encourage Handling: Developers are prompted to explicitly handle both success and failure paths, leading to more resilient applications.
- Propagate Errors Effectively: Failures, encapsulated in rich ErrorInfo objects, can be effortlessly passed through your application layers, carrying detailed context.
Zentient.Results is built on foundational architectural principles:
-
Immutability: All
Result
andResult<T>
instances are immutable once created. -
Composability (Functional Composition): Use extension methods like
Map
,Bind
, andThen
for fluent chaining of operations. -
Predictable Error Modeling: Failures are structured
ErrorInfo
objects, providing rich context. -
Status-Driven Outcomes: Integrates
IResultStatus
to represent operation status, often mirroring HTTP status codes. - Separation of Concerns: Decouples business logic from error reporting and recovery.
To add Zentient.Results to your project, simply use the .NET CLI:
dotnet add package Zentient.Results
Let's look at a simple scenario: validating an email address.
using Zentient.Results;
public class EmailService
{
public IResult<bool> IsEmailValid(string email)
{
if (string.IsNullOrWhiteSpace(email))
{
return Result.Validation<bool>(new ErrorInfo[]
{
new ErrorInfo(ErrorCategory.Validation, "EmailEmpty", "Email address cannot be empty.")
});
}
if (!email.Contains("@") || !email.Contains("."))
{
return Result.Validation<bool>(new ErrorInfo[]
{
new ErrorInfo(ErrorCategory.Validation, "InvalidFormat", "Email address format is invalid.")
});
}
return Result.Success(true, "Email address is valid.");
}
}
// How to use it:
public class Program
{
public static void Main(string[] args)
{
var service = new EmailService();
// Valid email
IResult<bool> validEmailResult = service.IsEmailValid("[email protected]");
validEmailResult.OnSuccess(isValid => Console.WriteLine($"Valid Email: {isValid} - {validEmailResult.Messages.FirstOrDefault()}"));
validEmailResult.OnFailure(errors => Console.WriteLine($"Error: {errors.First().Message}"));
Console.WriteLine("---");
// Invalid email (empty)
IResult<bool> emptyEmailResult = service.IsEmailValid("");
emptyEmailResult.OnSuccess(isValid => Console.WriteLine($"Valid Email: {isValid}"));
emptyEmailResult.OnFailure(errors => Console.WriteLine($"Error: {errors.First().Message}"));
Console.WriteLine("---");
// Invalid email (bad format)
IResult<bool> malformedEmailResult = service.IsEmailValid("invalid-email");
malformedEmailResult.OnSuccess(isValid => Console.WriteLine($"Valid Email: {isValid}"));
malformedEmailResult.OnFailure(errors => Console.WriteLine($"Error: {errors.First().Message}"));
}
}