FluentOutcomes 3.0.0-beta.2
dotnet add package FluentOutcomes --version 3.0.0-beta.2
NuGet\Install-Package FluentOutcomes -Version 3.0.0-beta.2
<PackageReference Include="FluentOutcomes" Version="3.0.0-beta.2" />
paket add FluentOutcomes --version 3.0.0-beta.2
#r "nuget: FluentOutcomes, 3.0.0-beta.2"
// Install FluentOutcomes as a Cake Addin
#addin nuget:?package=FluentOutcomes&version=3.0.0-beta.2&prerelease
// Install FluentOutcomes as a Cake Tool
#tool nuget:?package=FluentOutcomes&version=3.0.0-beta.2&prerelease
FluentOutcomes
FluentOutcomes is a lightweight .NET library to wrap a returning object while handling the potential errors that comes with it without throwing an exception and to provide a fluent and declarative way of dealing with if-else
statement.
NuGet Package
dotnet add package FluentOutcomes --version 3.0.0-beta.2
Table of Contents
Overview
FluentOutcome wrapper returned object in IOutcome
or IOutcome<T>
interface.
public interface IOutcome
{
bool IsSuccess { get; }
bool IsFailure { get; }
ResultTrace ResultTrace { get; }
bool HasMetadata { get; }
}
public interface IOutcome<T> : IOutcome
{
T Value { get; }
}
The best practice here to preface a method using Expect
or Try
keyword to mark whether the method is returning IOutcome
.
Examples
Expecting using success flow if statement
public IOutcome<User> ExpectGetUser(string username)
{
var result = _context.Users.SingleOrDefault(search => search.Username == username);
return Outcome
.Expect<User>() // declare the expected type
.SuccessIf(result is not null) // declare if (expected true value)
.Otherwise(error => { // else
error.Exception = new Exception()
})
.Return(result!); // return User object
}
Expecting using failure flow if statement
public IOutcome<User> ExpectGetUser(string username)
{
var result = _context.Users.SingleOrDefault(search => search.Username == username);
return Outcome
.Expect<User>()
.FailureIf(result is null)
.WithError(error => {
string message = $"404";
error.Exception = new Exception(message)
})
.Otherwise()
.Return(result!);
}
Overwrite return value
By default when the outcome IsFailure
it will return T Value
as default!
but it can be overwritten to return the value regardless the result.
var message = "Bar";
var foo = Outcome
.Expect<string>()
.FailureIf(message == "Bar") // fail
.Otherwise()
.Return(message, overwrite: true); // keep return "Bar" regardless
Immediate return OK and Fail
var foo = Outcome.Ok();
var bar = Outcome.Ok<string>("Hello, World");
var baz = Outcome.Fail();
var hur = Outcome.Fail("Sorry...");
var qux = Outcome.Fail(new Error());
var led = Outcome.Fail(error => { error.Exception = new Exception(); });
var bam = Outcome.Fail<string>();
var kis = Outcome.Fail<string>("My bad.");
var dim = Outcome.Fail<string>("Hello, World", overwrite: false);
var cok = Outcome.Fail<string>("Hello, World", new Error(), overwrite: false);
var kar = Outcome.Fail<string>("Hello, World", error => {
error.Exception = new Exception();
}, overwrite: false);
Fluent Boolean Operation
Using IfNot, Or, And, OrNot, and AndNot
IOutcome<string> outcome = Outcome
.Expect<string>()
.SuccessIfNot(true)
.Or(true)
.And(true)
.OrNot(false)
.AndNot(true)
.WithError(error => {
string message = "Wait, what?";
error.Exception = new Exception(message);
})
.Otherwise()
.Return("Hello, World");
Note: Please aware that using a long chain of complex boolean operation might resulting unpredicted output. Since the the operation was calculate against the previous condition, the precedence and order of evaluation was ignored. As for that scenario you can use anonymous method instead.
.SuccessIfNot(true)
.Or(true)
.And(true)
.OrNot(false)
.AndNot(true)
The boolean chain above is equal to:
(((!true || true) && true) || !false) && !true
It would be more intuitive and predicatable result if Or() operation is chain to FailureIf() clause, where And() is chain to SuccessIf().
Would return IsFailure is any of the following string is an empty string.
IOutcome<string> foo = Outcome
.Expect<string>()
.FailureIf(foo == "")
.Or(bar == "")
.Or(baz == "")
.Or(qux == "")
.Or(led == "")
.Or(dim == "")
.Or(bam == "")
.Or(cok == "")
.Otherwise()
.Return("Hello, World");
Would only return IsSucsess if all string is matched.
IOutcome<string> bar = Outcome
.Expect<string>()
.SuccessIf(foo == "Hey,")
.And(bar == "this")
.And(baz == "chain")
.And(qux == "is")
.And(led == "too")
.And(dim == "damn")
.And(bam == "long")
.And(cok == "!")
.Otherwise()
.Return($"{foo} {bar} {baz} {qux} {led} {dim} {bam} {cok}");
Func delegatec
In the case of complex boolean operation, you can use lamda expression as argument.
IOutcome<string> foo = Outcome
.Expect<string>()
.SuccessIf(() => {
bool condition = true && (false || false);
return condition;
})
.And(() => {
return (true && true) || false;
})
.Otherwise()
.Return("Hello, World");
return Outcome
.Expect<string>()
.SuccessIf(true)
.Otherwise()
.Return(() => {
return "I don't know why would you return something like this, but here you go.";
});
Metadata
Asserting metadata to a IOutcome
.
var foo = Outcome
.Expect()
.SuccessIf(true)
.Otherwise()
.Return()
.WithMetadata("Timestamp", DateTime.Now)
.WithMetadata("CurrentUser", CurrenttUser.Username);
Dictionary<string, object> Metadata = foo.ResultTrace.Metadata;
Metadata Assertion Level
return Outcome
.Expect()
.SuccessIf(true)
.Otherwise()
.Return()
.WithMetadata("Expected", 200, AssertLevel.SuccessOnly)
.WithMetadata("NotFound", 404, AssertLevel.FailureOnly);
Dictionary<string, object> Metadata = foo.ResultTrace.Metadata;
Configure Setting
You can configure IOutcome
and assert preface metadata to all IOutcome
.
Outcome.ConfigureSettings(config =>
{
config.SetAllCorrectMessage("Yay!"); // default: "OK"
config.SetDefaultErrorMessage("Oops..."); // default: "Unspecified error has occurred."
config.Metadata(x =>
{
x.AssertStatusResult();
x.AssertVerdict();
x.AssertGlobalMetadata("Timestamp", DateTime.Now);
});
});
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 is compatible. net5.0-windows was computed. 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 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 is compatible. |
.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.
-
.NETStandard 2.1
- No dependencies.
-
net5.0
- No dependencies.
-
net6.0
- No dependencies.
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 |
---|
v3.0.0-beta.2
- BREAKING CHANGES: Verdict -> IOutcome.ResultTrace.Verdict.
- BREAKING CHANGES: Error class is now under FluentOutcomes.Metadata namespace.
- ADDED: Add metadata support.
- ADDED: Add additional overloading Otherwise() clause.
- ADDED: Add additional overloading Fail() clause.
- ADDED: Add settings.
- ADDED: Add netstandard2.x backward compatibility.
v2.1.0
- ADDED: Add delegate (parameter) support of boolean operation and Return() clause.
- ADDED: Add option to overwrite the default! on Return() clause.
- ADDED: Add net5.0 backward compatibility.
v2.0.1
- Just patched things up.
v2.0.0
- BREAKING CHANGES: Expect() no longer chained to immediate return.
- REMOVED: Success() and Failure()
- ADDED: Add Ok() and Fail().
- ADDED: Add chained logic Or(), OrNot(), And() and AndNot() clause.
- ADDED: Add FailureIfNot() and SuccessIf() clause.
v1.2.0
- BREAKING CHANGES: WithError() clause is now chained Otherwise() clause instead.
- ADDED: Add Otherwise() clause after WithError() to indicate success.
- FIXED: FailureIf clause boolean negation.
v1.1.0
- ADDED: Add immediate return.
v1.0.0
- Initial release.