API Reference ResultTransformationExtensions - ulfbou/Zentient.Results GitHub Wiki

πŸ“˜ API Reference: static class – ResultTransformationExtensions

Namespace: Zentient.Results Assembly: Zentient.Results.dll Available since: v0.1.0


πŸ“– Summary

Provides extension methods for IResult and IResult<T> enabling functional transformations, fluent chaining, and conditional execution based on result success or failure.

This class enables ergonomic monadic composition (Bind, Then) and projection (Map) of result values, empowering developers to build failure-aware pipelines with minimal boilerplate.


πŸ’‘ Design Philosophy / Rationale

These extensions are grounded in functional programming principles, designed to simplify conditional workflows without if/else branching or exceptions.

Core Goals:

  • ♻️ Composable Control Flow: Enable functional chaining based on result state (Bind, Then).
  • 🎯 Selective Execution: Avoid unnecessary computations on failures.
  • 🧼 Fluent Expression: Provide ergonomic syntax for value projection (Map) and action triggering.
  • πŸ”§ Generic Agility: Support chaining across both typed and untyped results (IResult, IResult<T>).
  • πŸ” Null Safety: Guard all extension inputs with ArgumentNullException.

πŸ”– Type Signature

public static class ResultTransformationExtensions

πŸ”§ Methods

1. Map<TIn, TOut>(...)

  • Signature:

    public static IResult<TOut> Map<TIn, TOut>(this IResult<TIn> result, Func<TIn, TOut> selector)
  • Summary: Projects the value of a successful result into a new value type.

  • Parameters:

    • result (this IResult<TIn>): Source result to transform.
    • selector (Func<TIn, TOut>): Mapping function.
  • Return Value: IResult<TOut> with projected value or propagated failure.

  • Behavior: Executes selector only if the result is successful.

  • Exceptions Thrown: ArgumentNullException (if arguments are null).

  • Example Usage:

    var result = userResult.Map(u => u.Id);

2. Bind<TIn, TOut>(...) (async)

  • Signature:

    public static async Task<IResult<TOut>> Bind<TIn, TOut>(this IResult<TIn> result, Func<TIn, Task<IResult<TOut>>> next)
  • Summary: Asynchronously transforms the result using a next operation.

  • Return Value: Task<IResult<TOut>>

  • Behavior: Executes next only if the result is successful.

  • Example Usage:

    var result = await userResult.Bind(u => userService.GetDetailsAsync(u.Id));

3. Bind(...) (async, non-generic)

  • Signature:

    public static async Task<IResult> Bind(this IResult result, Func<Task<IResult>> next)

4. Then<TIn>(...)

  • Signature:

    public static IResult Then<TIn>(this IResult<TIn> result, Func<TIn, IResult> func)
  • Summary: Applies a side-effectful operation on success without transforming the result type.

  • Example Usage:

    var result = userResult.Then(u => audit.LogAccess(u));

5. Bind<TIn>(...) (non-generic)

  • Signature:

    public static IResult Bind<TIn>(this IResult<TIn> result, Func<TIn, IResult> binder)

6. Bind(...) (non-generic)

  • Signature:

    public static IResult Bind(this IResult result, Func<IResult> binder)

7. Bind<TOut>(...) (generic output)

  • Signature:

    public static IResult<TOut> Bind<TOut>(this IResult result, Func<IResult<TOut>> binder)

8. Then<TIn, TOut>(...)

  • Signature:

    public static IResult<TOut> Then<TIn, TOut>(this IResult<TIn> result, Func<TIn, IResult<TOut>> func)

9. Then(...) (non-generic)

  • Signature:

    public static IResult Then(this IResult result, Func<IResult> func)

10. Then<TOut>(...)

  • Signature:

    public static IResult<TOut> Then<TOut>(this IResult result, Func<IResult<TOut>> func)

πŸ§ͺ Usage Examples

var result = GetUser()
    .Bind(user => Validate(user))
    .Then(user => logger.LogInformation("User valid"))
    .Map(user => user.Id);
var dataResult = await Authenticate()
    .Bind(token => api.FetchAsync(token));

⚠️ Remarks

  • All methods are pure in behavior and favor declarative chaining over imperative control flow.
  • These methods do not mutate any result instanceβ€”they return new results.
  • Use Map for projection and Bind for chaining monadic operations.
  • Then is ideal for executing effects like logging or analytics conditionally.

🧩 Integration and Interoperability

Layer / Module Role
CQRS Pipelines For chaining handler logic.
Zentient.Endpoints Intermediate adapters use Bind to short-circuit failures.
Zentient.Results.Async Complemented with BindAsync, ThenAsync, and parallel tools.

πŸ“š See Also

  • IResult
  • IResult<T>
  • Result
  • ResultTryExtensions
  • ResultValueExtractionExtensions

🏷️ Tags

#API #ExtensionMethods #FunctionalComposition #Bind #Map #ResultPattern #ZentientCore


Last Updated: 2025-06-22 Version: 0.4.0

⚠️ **GitHub.com Fallback** ⚠️