REslava.Result.Flow β Native Companion Package
For projects using REslava.Result, the companion package REslava.Result.Flow adds two capabilities not possible in the library-agnostic package:
- Typed error edges β scans each step's method body for
new XxxError(...)constructions whereXxxError implements IError; renders-->|DatabaseError| FAILedges instead of generic fail arrows - IOperation chain walker β uses Roslyn's semantic model at the
IInvocationOperationlevel, which makes the pipeline entry-point call (e.g.CreateUser()) visible as its own node
dotnet add package REslava.Result.Flow
Add using REslava.Result.Flow; β the attribute type is injected automatically by the generator, no separate assembly reference needed.
/*
```mermaid
flowchart LR
N0_CreateUser["CreateUser<br/>User"]:::operation
N0_CreateUser --> N1_EnsureAsync
N1_EnsureAsync["EnsureAsync β‘<br/>User"]:::gatekeeper
N1_EnsureAsync -->|pass| N2_BindAsync
N1_EnsureAsync -->|ValidationError| FAIL
N2_BindAsync["BindAsync β‘<br/>User"]:::transform
N2_BindAsync -->|ok| N3_MapAsync
N2_BindAsync -->|DatabaseError| FAIL
N3_MapAsync["MapAsync β‘<br/>User β UserDto"]:::transform
FAIL([fail]):::failure
classDef gatekeeper fill:#e3e9fa,color:#3f5c9a
classDef transform fill:#e3f0e8,color:#2f7a5c
classDef failure fill:#f8e3e3,color:#b13e3e
classDef operation fill:#e8f4f0,color:#1c7e6f
```*/
[ResultFlow]
public Task<Result<UserDto>> RegisterAsync(RegisterCommand cmd) =>
CreateUser(cmd)
.EnsureAsync(IsEmailValid, u => new ValidationError("email", "invalid"))
.BindAsync(SaveUser)
.MapAsync(ToUserDto);
Paste the comment into mermaid.live β CreateUser becomes the pipeline root, ValidationError and DatabaseError appear as typed failure edges on their respective steps.
Here you can see the resulting diagram:
flowchart LR
N0_CreateUser["CreateUser<br/>User"]:::operation
N0_CreateUser --> N1_EnsureAsync
N1_EnsureAsync["EnsureAsync β‘<br/>User"]:::gatekeeper
N1_EnsureAsync -->|pass| N2_BindAsync
N1_EnsureAsync -->|ValidationError| FAIL
N2_BindAsync["BindAsync β‘<br/>User"]:::transform
N2_BindAsync -->|ok| N3_MapAsync
N2_BindAsync -->|DatabaseError| FAIL
N3_MapAsync["MapAsync β‘<br/>User β UserDto"]:::transform
FAIL([fail]):::failure
classDef gatekeeper fill:#e3e9fa,color:#3f5c9a
classDef transform fill:#e3f0e8,color:#2f7a5c
classDef failure fill:#f8e3e3,color:#b13e3e
classDef operation fill:#e8f4f0,color:#1c7e6f
Error scanning is best-effort β only scans methods in the same compilation; errors created but not returned may appear as false positives; helper methods are not recursively followed.
REslava.ResultFlow |
REslava.Result.Flow |
|
|---|---|---|
| Works with any library | β | β REslava.Result only |
| β‘ async annotation | β | β |
| Success type travel | β (first generic arg) | β (via IResultBase) |
| Typed error edges | β | β (IError body scan) |
| Entry-point call as node | β | β (IOperation walk) |
Which package should I use? Using REslava.Result? β use
REslava.Result.Flow. It produces richer diagrams with typed error edges and deeper type travel.
Feature Comparison
Using FluentResults, ErrorOr, LanguageExt, or any other library? β use
REslava.ResultFlow. Zero configuration needed forBindandMap(both are in the built-in convention dictionary).