|
17 | 17 | </div>
|
18 | 18 |
|
19 | 19 | - [Give it a star ⭐!](#give-it-a-star-)
|
20 |
| -- [Getting Started](#getting-started) |
| 20 | +- [Getting Started 🏃](#getting-started-) |
21 | 21 | - [Single Error](#single-error)
|
22 | 22 | - [This 👇🏽](#this-)
|
23 | 23 | - [Turns into this 👇🏽](#turns-into-this-)
|
24 | 24 | - [This 👇🏽](#this--1)
|
25 | 25 | - [Turns into this 👇🏽](#turns-into-this--1)
|
26 | 26 | - [Multiple Errors](#multiple-errors)
|
27 |
| -- [A more practical example](#a-more-practical-example) |
28 |
| -- [Dropping the exceptions throwing logic](#dropping-the-exceptions-throwing-logic) |
29 |
| -- [Usage](#usage) |
| 27 | +- [A more practical example 👷](#a-more-practical-example-) |
| 28 | +- [Dropping the exceptions throwing logic ✈️](#dropping-the-exceptions-throwing-logic-️) |
| 29 | +- [Usage 🛠️](#usage-️) |
30 | 30 | - [Creating an `ErrorOr<result>`](#creating-an-errororresult)
|
31 | 31 | - [From Value, using implicit conversion](#from-value-using-implicit-conversion)
|
32 | 32 | - [From Value, using `ErrorOrFactory.From`](#from-value-using-errororfactoryfrom)
|
|
44 | 44 | - [`MatchFirst` / `MatchFirstAsync`](#matchfirst--matchfirstasync)
|
45 | 45 | - [`Switch` / `SwitchAsync`](#switch--switchasync)
|
46 | 46 | - [`SwitchFirst` / `SwitchFirstAsync`](#switchfirst--switchfirstasync)
|
| 47 | + - [`Chain` / `ChainAsync`](#chain--chainasync) |
47 | 48 | - [Error Types](#error-types)
|
48 | 49 | - [Built-in Error Types](#built-in-error-types)
|
49 | 50 | - [Custom error types](#custom-error-types)
|
50 | 51 | - [Why would I want to categorize my errors?](#why-would-i-want-to-categorize-my-errors)
|
51 | 52 | - [Built in result types](#built-in-result-types)
|
52 |
| -- [How Is This Different From `OneOf<T0, T1>` or `FluentResults`?](#how-is-this-different-from-oneoft0-t1-or-fluentresults) |
53 |
| -- [Contribution](#contribution) |
54 |
| -- [Credits](#credits) |
55 |
| -- [License](#license) |
| 53 | +- [How Is This Different From `OneOf<T0, T1>` or `FluentResults`? 🤔](#how-is-this-different-from-oneoft0-t1-or-fluentresults-) |
| 54 | +- [Contribution 🤲](#contribution-) |
| 55 | +- [Credits 🙏](#credits-) |
| 56 | +- [License 🪪](#license-) |
56 | 57 |
|
57 | 58 | # Give it a star ⭐!
|
58 | 59 |
|
59 | 60 | Loving it? Show your support by giving this project a star!
|
60 | 61 |
|
61 |
| -# Getting Started |
| 62 | +# Getting Started 🏃 |
62 | 63 |
|
63 | 64 | ## Single Error
|
64 | 65 |
|
@@ -197,7 +198,7 @@ public async Task<ErrorOr<User>> CreateUserAsync(string name)
|
197 | 198 | }
|
198 | 199 | ```
|
199 | 200 |
|
200 |
| -# A more practical example |
| 201 | +# A more practical example 👷 |
201 | 202 |
|
202 | 203 | ```csharp
|
203 | 204 | [HttpGet("{id:guid}")]
|
@@ -247,7 +248,7 @@ return createUserResult.MatchFirst(
|
247 | 248 | error => error is Errors.User.DuplicateEmail ? Conflict() : InternalServerError());
|
248 | 249 | ```
|
249 | 250 |
|
250 |
| -# Dropping the exceptions throwing logic |
| 251 | +# Dropping the exceptions throwing logic ✈️ |
251 | 252 |
|
252 | 253 | You have validation logic such as `MediatR` behaviors, you can drop the exceptions throwing logic and simply return a list of errors from the pipeline behavior
|
253 | 254 |
|
@@ -303,7 +304,7 @@ public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TReques
|
303 | 304 | }
|
304 | 305 | ```
|
305 | 306 |
|
306 |
| -# Usage |
| 307 | +# Usage 🛠️ |
307 | 308 |
|
308 | 309 | ## Creating an `ErrorOr<result>`
|
309 | 310 |
|
@@ -509,6 +510,42 @@ await errorOrString.SwitchFirstAsync(
|
509 | 510 | firstError => { Console.WriteLine(firstError.Description); return Task.CompletedTask; });
|
510 | 511 | ```
|
511 | 512 |
|
| 513 | +### `Chain` / `ChainAsync` |
| 514 | + |
| 515 | +Multiple methods that return `ErrorOr<T>` can be chained as follows |
| 516 | + |
| 517 | +```csharp |
| 518 | +static ErrorOr<string> ConvertToString(int num) => num.ToString(); |
| 519 | +static ErrorOr<int> ConvertToInt(string str) => int.Parse(str); |
| 520 | + |
| 521 | +ErrorOr<string> errorOrString = "5"; |
| 522 | + |
| 523 | +ErrorOr<string> result = errorOrString |
| 524 | + .Chain(str => ConvertToInt(str)) |
| 525 | + .Chain(num => ConvertToString(num)) |
| 526 | + .Chain(str => ConvertToInt(str)) |
| 527 | + .Chain(num => ConvertToString(num)) |
| 528 | + .Chain(str => ConvertToInt(str)) |
| 529 | + .Chain(num => ConvertToString(num)); |
| 530 | +``` |
| 531 | + |
| 532 | +```csharp |
| 533 | +static Task<ErrorOr<string>> ConvertToString(int num) => Task.FromResult(ErrorOrFactory.From(num.ToString())); |
| 534 | +static Task<ErrorOr<int>> ConvertToInt(string str) => Task.FromResult(ErrorOrFactory.From(int.Parse(str))); |
| 535 | + |
| 536 | +ErrorOr<string> errorOrString = "5"; |
| 537 | + |
| 538 | +ErrorOr<string> result = await errorOrString |
| 539 | + .ChainAsync(str => ConvertToInt(str)) |
| 540 | + .ChainAsync(num => ConvertToString(num)) |
| 541 | + .ChainAsync(str => ConvertToInt(str)) |
| 542 | + .ChainAsync(num => ConvertToString(num)) |
| 543 | + .ChainAsync(str => ConvertToInt(str)) |
| 544 | + .ChainAsync(num => ConvertToString(num)); |
| 545 | +``` |
| 546 | + |
| 547 | +If any of the methods return an error, the chain will be broken and the error will be returned. |
| 548 | + |
512 | 549 | ## Error Types
|
513 | 550 |
|
514 | 551 | ### Built-in Error Types
|
@@ -599,19 +636,19 @@ ErrorOr<Deleted> DeleteUser(Guid id)
|
599 | 636 | }
|
600 | 637 | ```
|
601 | 638 |
|
602 |
| -# How Is This Different From `OneOf<T0, T1>` or `FluentResults`? |
| 639 | +# How Is This Different From `OneOf<T0, T1>` or `FluentResults`? 🤔 |
603 | 640 |
|
604 | 641 | It's similar to the others, just aims to be more intuitive and fluent.
|
605 | 642 | If you find yourself typing `OneOf<User, DomainError>` or `Result.Fail<User>("failure")` again and again, you might enjoy the fluent API of `ErrorOr<User>` (and it's also faster).
|
606 | 643 |
|
607 |
| -# Contribution |
| 644 | +# Contribution 🤲 |
608 | 645 |
|
609 | 646 | If you have any questions, comments, or suggestions, please open an issue or create a pull request 🙂
|
610 | 647 |
|
611 |
| -# Credits |
| 648 | +# Credits 🙏 |
612 | 649 |
|
613 | 650 | - [OneOf](https://github.com/mcintyre321/OneOf/tree/master/OneOf) - An awesome library which provides F# style discriminated unions behavior for C#
|
614 | 651 |
|
615 |
| -# License |
| 652 | +# License 🪪 |
616 | 653 |
|
617 | 654 | This project is licensed under the terms of the [MIT](https://github.com/mantinband/error-or/blob/main/LICENSE) license.
|
0 commit comments